1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Comptime updates, start of metaprogramming support

This commit is contained in:
Brian Fiete 2021-01-08 16:21:03 -08:00
parent be1c099f19
commit 3bbf2d8313
43 changed files with 1562 additions and 885 deletions

View file

@ -274,12 +274,38 @@ namespace System
}
[AttributeUsage(.Method | .Invocation)]
public struct ConstEvalAttribute : Attribute
[AttributeUsage(.Method)]
public struct ComptimeAttribute : Attribute
{
public this()
{
}
public bool OnlyFromComptime
{
set
{
}
}
public bool ConstEval
{
set
{
}
}
}
[AttributeUsage(.Invocation)]
public struct ConstEvalAttribute : Attribute
{
public this()
{
}
}
[AttributeUsage(.Method /*2*/)]
public struct IntrinsicAttribute : Attribute
{

View file

@ -1,7 +1,38 @@
using System.Reflection;
namespace System
{
[AttributeUsage(.Method)]
struct OnCompileAttribute : Attribute
{
public enum Kind
{
None,
TypeInit,
TypeDone
}
public this(Kind kind)
{
}
}
static class Compiler
{
public struct MethodBuilder
{
void* mNative;
public void Emit(String str)
{
Comptime_MethodBuilder_EmitStr(mNative, str);
}
public void Emit(Type type)
{
}
}
[LinkName("#CallerLineNum")]
public static extern int CallerLineNum;
@ -32,8 +63,8 @@ namespace System
[LinkName("#TimeLocal")]
public static extern String TimeLocal;
[LinkName("#IsConstEval")]
public static extern bool IsConstEval;
[LinkName("#IsComptime")]
public static extern bool IsComptime;
[LinkName("#IsBuilding")]
public static extern bool IsBuilding;
@ -44,11 +75,39 @@ namespace System
[LinkName("#CompileRev")]
public static extern int32 CompileRev;
[ConstEval]
[Comptime]
public static void Assert(bool cond)
{
if (!cond)
Runtime.FatalError("Assert failed");
}
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_EmitDefinition(int32 typeId, StringView text);
[Comptime(OnlyFromComptime=true)]
public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags)
{
MethodBuilder builder = .();
builder.[Friend]mNative = Comptime_CreateMethod((.)owner.TypeId, methodName, returnType, methodFlags);
return builder;
}
[Comptime(OnlyFromComptime=true)]
public static void EmitDefinition(Type owner, StringView text)
{
Comptime_EmitDefinition((.)owner.TypeId, text);
}
interface IComptimeTypeApply
{
void ApplyToType(Type type);
}
interface IComptimeMethodApply
{
void ApplyToMethod(Type type);
}
}
}

View file

@ -83,7 +83,7 @@ namespace System.Globalization
{
get
{
if (Compiler.IsConstEval)
if (Compiler.IsComptime)
return InitUserDefaultCulture();
if (tlCurrentCulture == null)
tlCurrentCulture = CultureInfo.DefaultThreadCurrentCulture ?? CultureInfo.UserDefaultCulture;

View file

@ -131,7 +131,7 @@ namespace System
public static T* AllocRawArrayUnmarked<T>(int size)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
if (Compiler.IsConstEval)
if (Compiler.IsComptime)
return new T[size]*(?);
// We don't want to use the default mark function because the GC will mark the entire array,
// whereas we have a custom marking routine because we only want to mark up to mSize

View file

@ -1235,7 +1235,7 @@ namespace System
// _isCustomFormat, _specifierIsUpper, _specifier & _precision.
this(CultureInfo cultureInfo)
{
if (Compiler.IsConstEval)
if (Compiler.IsComptime)
_cbuf = new char8[0];
else
_cbuf = sEmtpyBuf;

View file

@ -40,12 +40,12 @@ namespace System
return false;
}
#endif
extern Type ConstEval_GetType();
extern Type Comptime_GetType();
public Type GetType()
{
if (Compiler.IsConstEval)
return ConstEval_GetType();
if (Compiler.IsComptime)
return Comptime_GetType();
Type type;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
@ -65,8 +65,8 @@ namespace System
[NoShow]
Type RawGetType()
{
if (Compiler.IsConstEval)
return ConstEval_GetType();
if (Compiler.IsComptime)
return Comptime_GetType();
Type type;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS

View file

@ -35,6 +35,11 @@ namespace System
return .Ok(matched);
}
public virtual Result<MethodInfo, MethodError> GetMethod(int methodIdx)
{
return .Err(.NoResults);
}
public virtual Result<Object> CreateObject()
{
return .Err;
@ -61,6 +66,13 @@ namespace System.Reflection
return MethodInfo.Enumerator(this, bindingFlags);
}
public override Result<MethodInfo, MethodError> GetMethod(int methodIdx)
{
if ((methodIdx < 0) || (methodIdx >= mMethodDataCount))
return .Err(.NoResults);
return MethodInfo(this, &mMethodDataPtr[methodIdx]);
}
public override Result<Object> CreateObject()
{
if (mTypeClassVData == null)

View file

@ -471,19 +471,19 @@ namespace System
return (int32)mTypeId;
}
static extern Type ConstEval_GetTypeById(int32 typeId);
static extern Type Comptime_GetTypeById(int32 typeId);
protected static Type GetType(TypeId typeId)
{
if (Compiler.IsConstEval)
return ConstEval_GetTypeById((.)typeId);
if (Compiler.IsComptime)
return Comptime_GetTypeById((.)typeId);
return sTypes[(int32)typeId];
}
protected static Type GetType_(int32 typeId)
{
if (Compiler.IsConstEval)
return ConstEval_GetTypeById(typeId);
if (Compiler.IsComptime)
return Comptime_GetTypeById(typeId);
return sTypes[typeId];
}
@ -547,6 +547,11 @@ namespace System
return .Err;
}
public virtual Result<FieldInfo> GetField(int idx)
{
return .Err;
}
public virtual FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup)
{
return FieldInfo.Enumerator(null, bindingFlags);
@ -912,6 +917,13 @@ namespace System.Reflection
return .Err;
}
public override Result<FieldInfo> GetField(int fieldIdx)
{
if ((fieldIdx < 0) || (fieldIdx >= mFieldDataCount))
return .Err;
return FieldInfo(this, &mFieldDataPtr[fieldIdx]);
}
public override FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup)
{
return FieldInfo.Enumerator(this, bindingFlags);

View file

@ -130,6 +130,11 @@ namespace IDE
public virtual void RequestCancelBackground()
{
}
public virtual void RequestFastFinish()
{
}
public void CancelBackground()

View file

@ -61,6 +61,9 @@ namespace IDE.Compiler
[CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_Cancel(void* bfCompiler);
[CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_RequestFastFinish(void* bfCompiler);
[CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_ClearCompletionPercentage(void* bfCompiler);
@ -111,6 +114,12 @@ namespace IDE.Compiler
[CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_ForceRebuild(void* bfCompiler);
[CallingConvention(.Stdcall), CLink]
static extern char8* BfCompiler_GetEmitSource(void* bfCompiler, char8* fileName);
[CallingConvention(.Stdcall), CLink]
static extern int32 BfCompiler_GetEmitSourceVersion(void* bfCompiler, char8* fileName);
public enum HotTypeFlags
{
None = 0,
@ -267,6 +276,20 @@ namespace IDE.Compiler
BfCompiler_ForceRebuild(mNativeBfCompiler);
}
public bool GetEmitSource(StringView fileName, String outText)
{
char8* str = BfCompiler_GetEmitSource(mNativeBfCompiler, fileName.ToScopeCStr!());
if (str == null)
return false;
outText.Append(str);
return true;
}
public int32 GetEmitVersion(StringView fileName)
{
return BfCompiler_GetEmitSourceVersion(mNativeBfCompiler, fileName.ToScopeCStr!());
}
public void QueueSetPassInstance(BfPassInstance passInstance)
{
SetPassInstanceCommand command = new SetPassInstanceCommand();
@ -658,6 +681,15 @@ namespace IDE.Compiler
}
}
public override void RequestFastFinish()
{
if ([Friend]mThreadWorker.mThreadRunning || [Friend]mThreadWorkerHi.mThreadRunning)
{
if (mNativeBfCompiler != null)
BfCompiler_RequestFastFinish(mNativeBfCompiler);
}
}
public void ClearCompletionPercentage()
{
BfCompiler_ClearCompletionPercentage(mNativeBfCompiler);

View file

@ -1407,6 +1407,23 @@ namespace IDE
}
}
BfCompiler compiler = null;
if (fileName.Contains("$EmitR$"))
compiler = mBfResolveCompiler;
else if (fileName.Contains("$Emit$"))
compiler = mBfBuildCompiler;
if (compiler != null)
{
if (compiler.GetEmitSource(fileName, outBuffer))
{
if (onPreFilter != null)
onPreFilter();
return .Ok;
}
}
return Utils.LoadTextFile(fileName, outBuffer, autoRetry, onPreFilter);
}
@ -6145,6 +6162,16 @@ namespace IDE
useFilePath = scope:: String(useFilePath);
}
int32 emitRevision = -1;
//
{
int barPos = useFilePath.IndexOf('|');
if (barPos != -1)
{
emitRevision = int32.Parse(useFilePath.Substring(barPos + 1)).Value;
useFilePath.RemoveToEnd(barPos);
}
}
if ((useFilePath != null) && (!IDEUtils.FixFilePath(useFilePath)))
return null;
@ -6219,6 +6246,8 @@ namespace IDE
sourceViewPanelTab.mTabbedView.FinishTabAnim();
if (setFocus)
sourceViewPanel.FocusEdit();
sourceViewPanel.CheckEmitRevision();
}
}
@ -6236,6 +6265,7 @@ namespace IDE
}
else
success = sourceViewPanel.Show(useFilePath, !mInitialized);
sourceViewPanel.mEmitRevision = emitRevision;
if (!success)
{

View file

@ -153,6 +153,17 @@ namespace IDE.ui
}
}
public class HoverResolveTask
{
public int32 mCursorPos;
public String mResult ~ delete _;
public ~this()
{
NOP!();
}
}
public class SourceFindTask
{
public WaitEvent mDoneEvent = new WaitEvent() ~ delete _;
@ -306,6 +317,7 @@ namespace IDE.ui
public List<ResolveParams> mDeferredResolveResults = new .() ~ DeleteContainerAndItems!(_);
public bool mTrackedTextElementViewListDirty;
public String mFilePath ~ delete _;
public int32 mEmitRevision = -1;
public bool mIsBinary;
public String mAliasFilePath ~ delete _;
#if IDE_C_SUPPORT
@ -321,6 +333,7 @@ namespace IDE.ui
HTTPRequest mOldVerHTTPRequest ~ delete _;
IDEApp.ExecutionInstance mOldVerLoadExecutionInstance ~ { if (_ != null) _.mAutoDelete = true; };
SourceFindTask mSourceFindTask ~ delete _;
HoverResolveTask mHoverResolveTask ~ delete _;
bool mWantsFastClassify;
bool mWantsFullClassify; // This triggers a classify
bool mWantsFullRefresh; // If mWantsFullClassify is set, mWantsFullRefresh makes the whole thing refresh
@ -579,6 +592,8 @@ namespace IDE.ui
if (ResolveCompiler.mThreadWorkerHi.mThreadRunning)
{
ResolveCompiler.RequestFastFinish();
//Debug.WriteLine("Deferred DoAutoComplete");
DeleteAndNullify!(mQueuedAutoComplete);
mQueuedAutoComplete = new .();
@ -968,6 +983,11 @@ namespace IDE.ui
//return;
}*/
if (compiler.IsPerformingBackgroundOperation())
{
compiler.RequestFastFinish();
}
if (bfSystem == null)
return false;
@ -1023,7 +1043,7 @@ namespace IDE.ui
bool doBackground = (useResolveType == ResolveType.Classify) || (useResolveType == ResolveType.ClassifyFullRefresh);
if (mAsyncAutocomplete)
{
if ((useResolveType == .Autocomplete) || (useResolveType == .GetCurrentLocation) || (useResolveType == .GetSymbolInfo))
if ((useResolveType == .Autocomplete) || (useResolveType == .GetCurrentLocation) || (useResolveType == .GetSymbolInfo) || (useResolveType == .GetResultString))
doBackground = true;
}
@ -1111,7 +1131,9 @@ namespace IDE.ui
bool isHi = (resolveType != .ClassifyFullRefresh) && (resolveType != .Classify);
if (isHi)
{
Debug.Assert(!bfCompiler.mThreadWorkerHi.mThreadRunning);
}
else
Debug.Assert(!bfCompiler.mThreadWorker.mThreadRunning);
@ -1209,7 +1231,10 @@ namespace IDE.ui
var bfCompiler = BfResolveCompiler;
//var bfSystem = IDEApp.sApp.mBfResolveSystem;
//bfCompiler.StartTiming();
DoClassify(ResolveType.Classify, resolveParams);
ResolveType resolveType = ResolveType.Classify;
if (resolveParams != null)
resolveType = resolveParams.mResolveType;
DoClassify(resolveType, resolveParams);
//bfCompiler.StopTiming();
if (bfCompiler != null)
bfCompiler.QueueDeferredResolveAll();
@ -1600,6 +1625,11 @@ namespace IDE.ui
}
else if (resolveType == ResolveType.GetResultString)
{
if ((mHoverResolveTask != null) && (mHoverResolveTask.mCursorPos == resolveParams.mOverrideCursorPos))
{
mHoverResolveTask.mResult = new String(autocompleteInfo);
}
resolveParams.mResultString = new String(autocompleteInfo);
}
else if (resolveType == ResolveType.GetCurrentLocation)
@ -1664,7 +1694,7 @@ namespace IDE.ui
var bfCompiler = BfResolveCompiler;
//var compiler = ResolveCompiler;
bool isBackground = (resolveType == ResolveType.Classify) || (resolveType == ResolveType.ClassifyFullRefresh);
bool isBackground = (resolveType == ResolveType.Classify) || (resolveType == ResolveType.ClassifyFullRefresh) || (resolveType == .GetResultString);
bool fullRefresh = resolveType == ResolveType.ClassifyFullRefresh;
if (!isBackground)
@ -1775,15 +1805,18 @@ namespace IDE.ui
int cursorPos = mEditWidget.mEditWidgetContent.CursorTextPos;
/*if (resolveType == ResolveType.Autocomplete)
cursorPos--;*/
if ((resolveParams != null) && (resolveParams.mOverrideCursorPos != -1))
if (resolveParams != null)
{
if (resolveParams.mOverrideCursorPos != -1)
cursorPos = resolveParams.mOverrideCursorPos;
}
if ((resolveType == ResolveType.GetNavigationData) || (resolveType == ResolveType.GetFixits))
parser.SetAutocomplete(-1);
else
{
bool setAutocomplete = ((!isBackground) && (resolveType != ResolveType.RenameSymbol));
if ((resolveType == .Autocomplete) || (resolveType == .GetCurrentLocation) || (resolveType == .GetSymbolInfo))
if ((resolveType == .Autocomplete) || (resolveType == .GetCurrentLocation) || (resolveType == .GetSymbolInfo) || (resolveType == .GetResultString))
setAutocomplete = true;
if (setAutocomplete)
parser.SetAutocomplete(Math.Max(0, cursorPos));
@ -1866,7 +1899,9 @@ namespace IDE.ui
resolveParams.mCancelled = true;
if (resolveType == ResolveType.ClassifyFullRefresh)
{
QueueFullRefresh(false);
}
bfCompiler.QueueDeferredResolveAll();
}
}
@ -4640,6 +4675,7 @@ namespace IDE.ui
public void UpdateMouseover(bool mouseoverFired, bool mouseInbounds, int line, int lineChar)
{
#unwarn
CompilerBase compiler = ResolveCompiler;
@ -4839,7 +4875,7 @@ namespace IDE.ui
}
}
if (((mHoverWatch == null) && (mouseoverFired)) || (debugExpr == null) || (hasClangHoverErrorData))
if (((mHoverWatch == null) && (mouseoverFired)) || (debugExpr == null) || (hasClangHoverErrorData) || (mHoverResolveTask?.mResult != null))
{
float x;
float y;
@ -4857,18 +4893,22 @@ namespace IDE.ui
String origDebugExpr = null;
bool handlingHoverResolveTask = false;
if ((debugExpr != null) || (isOverMessage))
{
let resolveParams = scope ResolveParams();
resolveParams.mOverrideCursorPos = (int32)textIdx;
if (!gApp.mDebugger.IsPaused())
Classify(ResolveType.GetResultString, resolveParams);
if (!String.IsNullOrEmpty(resolveParams.mResultString))
if (mHoverResolveTask != null)
{
if (mHoverResolveTask.mCursorPos != textIdx)
DeleteAndNullify!(mHoverResolveTask);
}
if ((!String.IsNullOrEmpty(mHoverResolveTask?.mResult)))
{
origDebugExpr = scope:: String();
origDebugExpr.Set(debugExpr);
debugExpr.Set(resolveParams.mResultString);
debugExpr.Set(mHoverResolveTask.mResult);
if (debugExpr.StartsWith(':'))
{
@ -4889,6 +4929,12 @@ namespace IDE.ui
}
}
if (mHoverResolveTask?.mResult != null)
{
handlingHoverResolveTask = true;
DeleteAndNullify!(mHoverResolveTask);
}
if (!triedShow)
{
mHoverWatch.Show(this, x, y, debugExpr, debugExpr);
@ -4899,6 +4945,22 @@ namespace IDE.ui
if ((!didShow) &&
((debugExpr == null) || (isOverMessage) || (!mHoverWatch.Show(this, x, y, origDebugExpr ?? debugExpr, debugExpr))))
{
if (mHoverResolveTask == null)
{
if ((!handlingHoverResolveTask) && (!ResolveCompiler.mThreadWorkerHi.mThreadRunning))
{
ResolveParams resolveParams = new .();
resolveParams.mOverrideCursorPos = (int32)textIdx;
Classify(ResolveType.GetResultString, resolveParams);
//Debug.WriteLine($"GetResultString {resolveParams} {resolveParams.mInDeferredList}");
if (!resolveParams.mInDeferredList)
delete resolveParams;
mHoverResolveTask = new HoverResolveTask();
mHoverResolveTask.mCursorPos = (int32)textIdx;
}
}
#if IDE_C_SUPPORT
if ((mIsClang) && (textIdx != -1))
{
@ -4994,7 +5056,6 @@ namespace IDE.ui
{
mWantsFullRefresh = true;
mRefireMouseOverAfterRefresh = true;
//Debug.WriteLine("Full refresh...");
}
}
@ -5026,7 +5087,6 @@ namespace IDE.ui
{
if (mHoverWatch.mCloseDelay > 0)
{
//Debug.WriteLine("mHoverWatch.mCloseCountdown = 20");
mHoverWatch.mCloseDelay--;
mHoverWatch.mCloseCountdown = 20;
}
@ -5042,7 +5102,6 @@ namespace IDE.ui
}
else
{
//Debug.WriteLine("mCloseCountdown = 0");
mHoverWatch.mCloseCountdown = 0;
}
}
@ -5088,7 +5147,7 @@ namespace IDE.ui
#if IDE_C_SUPPORT
hasClangHoverErrorData = mClangHoverErrorData != null;
#endif
if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData)) &&
if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData) || (mHoverResolveTask?.mResult != null)) &&
(mousePos.x >= 0))
{
int line;
@ -5105,455 +5164,6 @@ namespace IDE.ui
}
}
public void UpdateMouseover2()
{
if (mWidgetWindow == null)
return;
if (CheckLeftMouseover())
{
return;
}
if ((DarkTooltipManager.sTooltip != null) && (DarkTooltipManager.sTooltip.mRelWidget == this))
DarkTooltipManager.CloseTooltip();
if (!CheckAllowHoverWatch())
{
return;
}
/*if ((mHoverWatch != null) && (mHoverWatch.mCloseDelay > 0))
return;*/
var editWidgetContent = mEditWidget.Content;
Point mousePos;
bool mouseoverFired = DarkTooltipManager.CheckMouseover(editWidgetContent, 10, out mousePos);
#unwarn
CompilerBase compiler = ResolveCompiler;
bool hasClangHoverErrorData = false;
#if IDE_C_SUPPORT
hasClangHoverErrorData = mClangHoverErrorData != null;
#endif
if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData)) &&
(mousePos.x >= 0))
{
int line;
int lineChar;
String debugExpr = null;
BfSystem bfSystem = IDEApp.sApp.mBfResolveSystem;
BfPassInstance passInstance = null;
BfParser parser = null;
int textIdx = -1;
bool isOverMessage = false;
float overflowX;
if (editWidgetContent.GetLineCharAtCoord(mousePos.x, mousePos.y, out line, out lineChar, out overflowX))
{
textIdx = editWidgetContent.GetTextIdx(line, lineChar);
int startIdx = editWidgetContent.GetTextIdx(line, lineChar);
uint8 checkFlags = (uint8)SourceElementFlags.Error;
if (!IDEApp.sApp.mDebugger.mIsRunning)
{
// Prioritize debug info over warning when we are debugging
checkFlags |= (uint8)SourceElementFlags.Warning;
}
if ((editWidgetContent.mData.mText[startIdx].mDisplayFlags & checkFlags) != 0)
isOverMessage = true;
bool doSimpleMouseover = false;
if ((editWidgetContent.mSelection != null) &&
(textIdx >= editWidgetContent.mSelection.Value.MinPos) &&
(textIdx < editWidgetContent.mSelection.Value.MaxPos))
{
debugExpr = scope:: String();
editWidgetContent.GetSelectionText(debugExpr);
}
else if (mIsBeefSource)
{
if (bfSystem != null)
{
parser = bfSystem.CreateEmptyParser(null);
var text = scope String();
mEditWidget.GetText(text);
parser.SetSource(text, mFilePath);
parser.SetAutocomplete(textIdx);
passInstance = bfSystem.CreatePassInstance("Mouseover");
parser.SetCompleteParse();
parser.Parse(passInstance, !mIsBeefSource);
parser.Reduce(passInstance);
debugExpr = scope:: String();
if (parser.GetDebugExpressionAt(textIdx, debugExpr))
{
if (debugExpr.StartsWith("`"))
debugExpr[0] = ':';
else if (debugExpr.StartsWith(":"))
debugExpr = null;
}
}
}
else if (mIsClang)
doSimpleMouseover = true;
if (doSimpleMouseover)
SimpleMouseover: do
{
int endIdx = startIdx;
String sb = scope:: String();
bool isInvalid = false;
bool prevWasSpace = false;
if (editWidgetContent.mData.mText[startIdx].mChar.IsWhiteSpace)
break;
startIdx--;
while (startIdx > 0)
{
var char8Data = editWidgetContent.mData.mText[startIdx];
if (char8Data.mDisplayTypeId == (uint8)SourceElementType.Comment)
{
if (startIdx == endIdx - 1)
{
// Inside comment
isInvalid = true;
break;
}
}
else
{
char8 c = (char8)char8Data.mChar;
if ((c == ' ') || (c == '\t'))
{
// Ignore
prevWasSpace = true;
}
else if (c == '\n')
{
break;
}
else
{
if (c == '>')
{
// Is this "->"?
if ((startIdx > 1) && ((char8)editWidgetContent.mData.mText[startIdx - 1].mChar == '-'))
{
sb.Insert(0, "->");
startIdx--;
}
else
break;
}
else if (c == ':')
{
// Is this "::"?
if ((startIdx > 1) && ((char8)editWidgetContent.mData.mText[startIdx - 1].mChar == ':'))
{
sb.Insert(0, "::");
startIdx--;
}
else
break;
}
else if (c == '.')
sb.Insert(0, c);
else if ((c == '_') || (c.IsLetterOrDigit))
{
if (prevWasSpace)
break;
sb.Insert(0, c);
}
else
break;
prevWasSpace = false;
}
}
startIdx--;
}
prevWasSpace = false;
while ((endIdx < editWidgetContent.mData.mTextLength) && (endIdx > startIdx))
{
var char8Data = editWidgetContent.mData.mText[endIdx];
if (char8Data.mDisplayTypeId == (uint8)SourceElementType.Comment)
{
// Ignore
prevWasSpace = true;
}
else
{
char8 c = (char8)char8Data.mChar;
if ((c == ' ') || (c == '\t'))
{
// Ignore
prevWasSpace = true;
}
else if ((c == '_') || (c.IsLetterOrDigit))
{
if (prevWasSpace)
break;
sb.Append(c);
}
else
break;
prevWasSpace = false;
}
endIdx++;
}
if (!isInvalid)
debugExpr = sb;
}
}
bool triedShow = false;
if (mHoverWatch != null)
{
if (debugExpr != null)
{
if (mHoverWatch.mEvalString != debugExpr)
{
mHoverWatch.Close();
mHoverWatch = null;
}
else
triedShow = true;
}
}
if (((mHoverWatch == null) && (mouseoverFired)) || (debugExpr == null) || (hasClangHoverErrorData))
{
float x;
float y;
editWidgetContent.GetTextCoordAtLineChar(line, lineChar, out x, out y);
bool hasHoverWatchOpen = (mHoverWatch != null) && (mHoverWatch.mListView != null);
if (mHoverWatch == null)
mHoverWatch = new HoverWatch();
if (debugExpr != null)
triedShow = true;
bool didShow = false;
//if ((debugExpr == "var") || (debugExpr == "let"))
String origDebugExpr = null;
if ((debugExpr != null) || (isOverMessage))
{
let resolveParams = scope ResolveParams();
resolveParams.mOverrideCursorPos = (int32)textIdx;
Classify(ResolveType.GetResultString, resolveParams);
if (!String.IsNullOrEmpty(resolveParams.mResultString))
{
origDebugExpr = scope:: String();
origDebugExpr.Set(debugExpr);
debugExpr.Set(resolveParams.mResultString);
}
if (!triedShow)
{
mHoverWatch.Show(this, x, y, debugExpr, debugExpr);
triedShow = true;
}
}
if ((!didShow) &&
((debugExpr == null) || (isOverMessage) || (!mHoverWatch.Show(this, x, y, origDebugExpr ?? debugExpr, debugExpr))))
{
#if IDE_C_SUPPORT
if ((mIsClang) && (textIdx != -1))
{
bool hasErrorFlag = (mEditWidget.Content.mData.mText[textIdx].mDisplayFlags != 0);
if (hasErrorFlag)
{
if (!compiler.IsPerformingBackgroundOperation())
{
bool hadValidError = false;
if (mClangHoverErrorData != null)
{
String[] stringParts = String.StackSplit!(mClangHoverErrorData, '\t');
int startIdx = (int32)int32.Parse(stringParts[0]);
int endIdx = (int32)int32.Parse(stringParts[1]);
if ((textIdx >= startIdx) && (textIdx < endIdx))
{
hadValidError = true;
triedShow = true;
mHoverWatch.Show(this, x, y, scope String(":", stringParts[2]));
if (debugExpr != null)
mHoverWatch.mEvalString.Set(debugExpr); // Set to old debugStr for comparison
else
mHoverWatch.mEvalString.Clear();
}
}
if (!hadValidError)
{
mErrorLookupTextIdx = (int32)textIdx;
Classify(ResolveType.Classify);
triedShow = false;
}
}
}
else
{
triedShow = false;
delete mClangHoverErrorData;
mClangHoverErrorData = null;
}
}
#endif
if ((parser != null) && (mIsBeefSource))
ErrorScope:
{
//TODO: Needed this?
/*var resolvePassData = parser.CreateResolvePassData();
defer (scope) delete resolvePassData;
bfSystem.NotifyWillRequestLock(1);
bfSystem.Lock(1);
parser.BuildDefs(passInstance, resolvePassData, false);
BfResolveCompiler.ClassifySource(passInstance, parser, resolvePassData, null);*/
BfPassInstance.BfError bestError = scope BfPassInstance.BfError();
for (var bfError in mErrorList)
{
if (bfError.mIsWhileSpecializing)
continue;
if ((textIdx >= bfError.mSrcStart) && (textIdx < bfError.mSrcEnd))
{
if ((bestError.mError == null) || (bestError.mIsWarning) || (bestError.mIsPersistent))
bestError = bfError;
}
}
String showMouseoverString = null;
if (bestError.mError != null)
{
showMouseoverString = scope:: String(":", bestError.mError);
if (bestError.mMoreInfo != null)
{
for (var moreInfo in bestError.mMoreInfo)
{
showMouseoverString.AppendF("\n@{0}\t{1}\t{2}", moreInfo.mFilePath, moreInfo.mSrcStart, moreInfo.mError);
}
}
}
else
{
var flags = (SourceElementFlags)editWidgetContent.mData.mText[textIdx].mDisplayFlags;
if ((flags.HasFlag(.Error)) || (flags.HasFlag(.Warning)))
{
mWantsFullRefresh = true;
mRefireMouseOverAfterRefresh = true;
//Debug.WriteLine("Full refresh...");
}
}
if (showMouseoverString != null)
{
triedShow = true;
mHoverWatch.Show(this, x, y, showMouseoverString, showMouseoverString);
if (debugExpr != null)
mHoverWatch.mEvalString.Set(debugExpr); // Set to old debugStr for comparison
}
else
triedShow = false;
}
}
if (!hasHoverWatchOpen)
mHoverWatch.mOpenMousePos = DarkTooltipManager.sLastRelMousePos;
}
// Not used?
if ((mHoverWatch != null) && (mHoverWatch.mTextPanel != this))
{
mHoverWatch.Close();
mHoverWatch = null;
}
if (mHoverWatch != null)
{
if ((!triedShow) && (!IDEApp.sApp.HasPopupMenus()))
{
if (mHoverWatch.mCloseDelay > 0)
{
//Debug.WriteLine("mHoverWatch.mCloseCountdown = 20");
mHoverWatch.mCloseDelay--;
mHoverWatch.mCloseCountdown = 20;
}
else
{
mHoverWatch.Close();
mHoverWatch = null;
#if IDE_C_SUPPORT
delete mClangHoverErrorData;
mClangHoverErrorData = null;
#endif
}
}
else
{
//Debug.WriteLine("mCloseCountdown = 0");
mHoverWatch.mCloseCountdown = 0;
}
}
if (passInstance != null)
delete passInstance;
if (parser != null)
{
delete parser;
mWantsParserCleanup = true;
}
}
#if IDE_C_SUPPORT
delete mClangHoverErrorData;
mClangHoverErrorData = null;
#endif
/*if ((mIsClang) && (!compiler.IsPerformingBackgroundOperation()))
{
bool hadValidError = false;
if (mClangHoverErrorData != null)
{
int textIdx = -1;
int line;
int lineChar;
if (editWidgetContent.GetLineCharAtCoord(mousePos.x, mousePos.y, out line, out lineChar))
textIdx = editWidgetContent.GetTextIdx(line, lineChar);
string[] stringParts = mClangHoverErrorData.Split('\t');
int startIdx = int.Parse(stringParts[0]);
int endIdx = int.Parse(stringParts[1]);
if ((textIdx >= startIdx) && (textIdx < endIdx))
{
hadValidError = true;
mHoverWatch.Show(this, x, y, ":" + stringParts[2]);
mHoverWatch.mEvalString.Set(debugExpr); // Set to old debugStr for comparison
}
}
}*/
}
void DuplicateEditState(out EditWidgetContent.CharData[] char8Data, out IdSpan char8IdData)
{
var srcCharData = mEditWidget.Content.mData.mText;
@ -5840,6 +5450,13 @@ namespace IDE.ui
checkIdx++;
continue;
}
if (!resolveResult.mWaitEvent.WaitFor(0))
{
if (waitTime != 0)
ResolveCompiler.RequestFastFinish();
}
if (!resolveResult.mWaitEvent.WaitFor(waitTime))
{
checkIdx++;
@ -5847,6 +5464,9 @@ namespace IDE.ui
}
mDeferredResolveResults.RemoveAt(checkIdx);
}
//Debug.WriteLine($"HandleResolveResult {resolveResult}");
HandleResolveResult(resolveResult.mResolveType, resolveResult.mAutocompleteInfo, resolveResult);
//Debug.WriteLine("ProcessDeferredResolveResults finished {0}", resolveResult.mResolveType);
@ -5887,12 +5507,15 @@ namespace IDE.ui
{
MarkDirty();
if (resolveResult.mPassInstance.HadSignatureChanges())
{
mWantsFullRefresh = true;
}
}
}
/*if (checkIt)
Debug.Assert(data.mDisplayTypeId == 8);*/
//Debug.WriteLine($"Deleting {resolveResult}");
delete resolveResult;
}
}
@ -6368,6 +5991,9 @@ namespace IDE.ui
mLockFlashPct = 0;
MarkDirty();
}
if ((mEmitRevision >= 0) && ((mUpdateCnt % 30) == 0))
CheckEmitRevision();
}
void InjectErrors(BfPassInstance processingPassInstance, EditWidgetContent.CharData[] processResolveCharData, IdSpan processCharIdSpan, bool keepPersistentErrors)
@ -6396,10 +6022,14 @@ namespace IDE.ui
int32 errorCount = processingPassInstance.GetErrorCount();
mErrorList.Capacity = mErrorList.Count + errorCount;
bool hadNonDeferredErrors = false;
for (int32 errorIdx = 0; errorIdx < errorCount; errorIdx++)
{
BfPassInstance.BfError bfError = new BfPassInstance.BfError();
processingPassInstance.GetErrorData(errorIdx, bfError);
if (!bfError.mIsDeferred)
hadNonDeferredErrors = true;
for (int32 moreInfoIdx < bfError.mMoreInfoCount)
{
@ -6425,6 +6055,9 @@ namespace IDE.ui
if (bfError.mIsWhileSpecializing)
continue;
if ((bfError.mIsDeferred) && (hadNonDeferredErrors))
continue;
if (bfError.mIsPersistent)
{
if (bfError.mIdSpan.IsEmpty)
@ -6823,5 +6456,27 @@ namespace IDE.ui
return false;
}
public void CheckEmitRevision()
{
if (mEmitRevision != -1)
{
BfCompiler compiler = null;
if (mFilePath.Contains("$EmitR$"))
compiler = gApp.mBfResolveCompiler;
else if (mFilePath.Contains("$Emit$"))
compiler = gApp.mBfBuildCompiler;
if (compiler != null)
{
int32 version = compiler.GetEmitVersion(mFilePath);
if ((version >= 0) && (version != mEmitRevision))
{
mEmitRevision = version;
Reload();
}
}
}
}
}
}

View file

@ -880,6 +880,21 @@ void BeIRCodeGen::Read(BeValue*& beValue)
beValue = mBeModule->CreateUndefValue(type);
return;
}
else if (constType == BfConstType_TypeOf)
{
CMD_PARAM(BeType*, type);
beValue = mReflectDataMap[type];
BF_ASSERT(beValue != NULL);
return;
}
else if (constType == BfConstType_TypeOf_WithData)
{
CMD_PARAM(BeType*, type);
CMD_PARAM(BeValue*, value);
mReflectDataMap[type] = value;
beValue = value;
return;
}
bool isSigned = false;
BeType* llvmConstType = GetBeType(typeCode, isSigned);
@ -1969,6 +1984,13 @@ void BeIRCodeGen::HandleNextCmd()
//SetResult(curId, globalVariable);
}
break;
case BfIRCmd_SetReflectTypeData:
{
CMD_PARAM(BeType*, type);
CMD_PARAM(BeValue*, value);
mReflectDataMap[type] = value;
}
break;
case BfIRCmd_CreateBlock:
{
CMD_PARAM(String, name);

View file

@ -89,6 +89,7 @@ public:
Dictionary<int, BeIRTypeEntry> mTypes;
Dictionary<BeType*, BeDbgType*> mOnDemandTypeMap;
Dictionary<BeType*, BeValue*> mReflectDataMap;
Array<int> mConfigConsts;
public:

View file

@ -946,6 +946,14 @@ BfParser* BfAstNode::GetParser()
return sourceData->ToParser();
}
bool BfAstNode::IsEmitted()
{
auto parser = GetParser();
if (parser == NULL)
return false;
return parser->mIsEmitted;
}
bool BfAstNode::IsFromParser(BfParser* parser)
{
if (parser == NULL)

View file

@ -1088,6 +1088,7 @@ public:
BfSourceData* GetSourceData();
BfParserData* GetParserData();
BfParser* GetParser();
bool IsEmitted();
bool IsFromParser(BfParser* parser);
String ToString();
StringView ToStringView();

View file

@ -346,6 +346,8 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
memset(&mStats, 0, sizeof(mStats));
mCompletionPct = 0;
mCanceling = false;
mFastFinish = false;
mHasQueuedTypeRebuilds = false;
mIsResolveOnly = isResolveOnly;
mResolvePassData = NULL;
mPassInstance = NULL;
@ -397,6 +399,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mActionTypeDef = NULL;
mEnumTypeDef = NULL;
mFriendAttributeTypeDef = NULL;
mComptimeAttributeTypeDef = NULL;
mConstEvalAttributeTypeDef = NULL;
mNoExtensionAttributeTypeDef = NULL;
mCheckedAttributeTypeDef = NULL;
@ -409,10 +412,13 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mInlineAttributeTypeDef = NULL;
mThreadTypeDef = NULL;
mInternalTypeDef = NULL;
mCompilerTypeDef = NULL;
mDiagnosticsDebugTypeDef = NULL;
mIDisposableTypeDef = NULL;
mIPrintableTypeDef = NULL;
mIHashableTypeDef = NULL;
mIComptimeTypeApply = NULL;
mIComptimeMethodApply = NULL;
mLinkNameAttributeTypeDef = NULL;
mCallingConventionAttributeTypeDef = NULL;
mMethodRefTypeDef = NULL;
@ -447,6 +453,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mWarnAttributeTypeDef = NULL;
mIgnoreErrorsAttributeTypeDef = NULL;
mReflectAttributeTypeDef = NULL;
mOnCompileAttributeTypeDef = NULL;
mLastAutocompleteModule = NULL;
@ -3919,6 +3926,8 @@ void BfCompiler::ProcessAutocompleteTempType()
return;
}
mFastFinish = false;
SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, NULL);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, NULL);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, NULL);
@ -6529,6 +6538,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mOutputDirectory = outputDirectory;
mSystem->StartYieldSection();
mFastFinish = false;
mHasQueuedTypeRebuilds = false;
mCanceling = false;
mSystem->CheckLockYield();
@ -6611,6 +6622,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mActionTypeDef = _GetRequiredType("System.Action");
mEnumTypeDef = _GetRequiredType("System.Enum");
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute");
mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute");
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");
mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute");
@ -6624,10 +6636,13 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
mThreadTypeDef = _GetRequiredType("System.Threading.Thread");
mInternalTypeDef = _GetRequiredType("System.Internal");
mCompilerTypeDef = _GetRequiredType("System.Compiler");
mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
mIHashableTypeDef = _GetRequiredType("System.IHashable");
mIComptimeTypeApply = _GetRequiredType("System.IComptimeTypeApply");
mIComptimeMethodApply = _GetRequiredType("System.IComptimeMethodApply");
mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute");
mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute");
mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1);
@ -6662,6 +6677,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute");
mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute");
mOnCompileAttributeTypeDef = _GetRequiredType("System.OnCompileAttribute");
for (int i = 0; i < BfTypeCode_Length; i++)
mContext->mPrimitiveStructTypes[i] = NULL;
@ -7213,6 +7229,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
}
mCodeGen.ProcessErrors(mPassInstance, mCanceling);
mCEMachine->CompileDone();
// This has to happen after codegen because we may delete modules that are referenced in codegen
mContext->Cleanup();
if ((!IsHotCompile()) && (!mIsResolveOnly) && (!mCanceling))
@ -7346,7 +7364,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mContext->ValidateDependencies();
return !didCancel;
return !didCancel && !mHasQueuedTypeRebuilds;
}
bool BfCompiler::Compile(const StringImpl& outputDirectory)
@ -7380,11 +7398,19 @@ void BfCompiler::ClearResults()
void BfCompiler::Cancel()
{
mCanceling = true;
mFastFinish = true;
mHadCancel = true;
BfLogSysM("BfCompiler::Cancel\n");
BpEvent("BfCompiler::Cancel", "");
}
void BfCompiler::RequestFastFinish()
{
mFastFinish = true;
BfLogSysM("BfCompiler::RequestFastFinish\n");
BpEvent("BfCompiler::RequestFastFinish", "");
}
//#define WANT_COMPILE_LOG
void BfCompiler::CompileLog(const char* fmt ...)
@ -8538,6 +8564,38 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
return result;
}
int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
{
int lastDollarPos = (int)fileName.LastIndexOf('$');
if (lastDollarPos == -1)
return -1;
int dotPos = (int)fileName.LastIndexOf('.');
if (dotPos == -1)
return -1;
String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);
int revisionId = (int)atoi(typeIdStr.c_str());
int typeId = (int)atoi(typeIdStr.c_str());
if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize))
return -1;
auto type = mContext->mTypes[typeId];
if (type == NULL)
return -1;
auto typeInst = type->ToTypeInstance();
if (typeInst == NULL)
return -1;
auto typeDef = typeInst->mTypeDef;
if (typeDef->mEmitParser == NULL)
return -1;
if (outBuffer != NULL)
outBuffer->Append(typeDef->mEmitParser->mSrc, typeDef->mEmitParser->mSrcLength);
return typeInst->mRevision;
}
//////////////////////////////////////////////////////////////////////////
PerfManager* BfGetPerfManager(BfParser* bfParser);
@ -8738,6 +8796,11 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_Cancel(BfCompiler* bfCompiler)
bfCompiler->Cancel();
}
BF_EXPORT void BF_CALLTYPE BfCompiler_RequestFastFinish(BfCompiler* bfCompiler)
{
bfCompiler->RequestFastFinish();
}
BF_EXPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(BfCompiler* bfCompiler)
{
bfCompiler->ClearBuildCache();
@ -9251,3 +9314,17 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler)
bfCompiler->mOptions.mForceRebuildIdx++;
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetEmitSource(BfCompiler* bfCompiler, char* fileName)
{
String& outString = *gTLStrReturn.Get();
outString.clear();
bfCompiler->GetEmitSource(fileName, &outString);
if (outString.IsEmpty())
return NULL;
return outString.c_str();
}
BF_EXPORT int32 BF_CALLTYPE BfCompiler_GetEmitSourceVersion(BfCompiler* bfCompiler, char* fileName)
{
return bfCompiler->GetEmitSource(fileName, NULL);
}

View file

@ -323,6 +323,8 @@ public:
BfCodeGen mCodeGen;
String mOutputDirectory;
bool mCanceling;
bool mFastFinish;
bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild
bool mHadCancel;
bool mWantsDeferMethodDecls;
bool mInInvalidState;
@ -362,10 +364,13 @@ public:
BfTypeDef* mThreadTypeDef;
BfTypeDef* mInternalTypeDef;
BfTypeDef* mCompilerTypeDef;
BfTypeDef* mDiagnosticsDebugTypeDef;
BfTypeDef* mIDisposableTypeDef;
BfTypeDef* mIPrintableTypeDef;
BfTypeDef* mIHashableTypeDef;
BfTypeDef* mIComptimeTypeApply;
BfTypeDef* mIComptimeMethodApply;
BfTypeDef* mMethodRefTypeDef;
BfTypeDef* mNullableTypeDef;
@ -403,6 +408,7 @@ public:
BfTypeDef* mDisableChecksAttributeTypeDef;
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
BfTypeDef* mFriendAttributeTypeDef;
BfTypeDef* mComptimeAttributeTypeDef;
BfTypeDef* mConstEvalAttributeTypeDef;
BfTypeDef* mNoExtensionAttributeTypeDef;
BfTypeDef* mCheckedAttributeTypeDef;
@ -417,6 +423,7 @@ public:
BfTypeDef* mWarnAttributeTypeDef;
BfTypeDef* mIgnoreErrorsAttributeTypeDef;
BfTypeDef* mReflectAttributeTypeDef;
BfTypeDef* mOnCompileAttributeTypeDef;
int mCurTypeId;
int mTypeInitCount;
@ -493,9 +500,11 @@ public:
void ProcessAutocompleteTempType();
void GetSymbolReferences();
void Cancel();
void RequestFastFinish();
String GetTypeDefList();
String GetTypeDefMatches(const StringImpl& searchSrc);
String GetTypeDefInfo(const StringImpl& typeName);
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
void CompileLog(const char* fmt ...);
void ReportMemory(MemReporter* memReporter);

View file

@ -36,7 +36,7 @@ BfConstResolver::BfConstResolver(BfModule* bfModule) : BfExprEvaluator(bfModule)
BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfConstResolveFlags flags)
{
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval);
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
// Handle the 'int[?] val = .(1, 2, 3)' case
if ((flags & BfConstResolveFlag_ArrayInitSize) != 0)

View file

@ -737,7 +737,7 @@ void BfContext::HandleChangedTypeDef(BfTypeDef* typeDef, bool isAutoCompleteTemp
}
}
if (!typeDef->mIsPartial)
if ((!typeDef->mIsPartial) && (!isAutoCompleteTempType))
{
if ((typeDef->mDefState == BfTypeDef::DefState_New) ||
(typeDef->mDefState == BfTypeDef::DefState_Deleted) ||
@ -1026,6 +1026,11 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
delete typeInst->mTypeInfoEx;
typeInst->mTypeInfoEx = NULL;
typeInst->mTypeDef->ClearEmitted();
for (auto localMethod : typeInst->mOwnedLocalMethods)
delete localMethod;
typeInst->mOwnedLocalMethods.Clear();
if (typeInst->IsGenericTypeInstance())
{
auto genericTypeInstance = (BfTypeInstance*)typeInst;
@ -2851,7 +2856,24 @@ void BfContext::Cleanup()
for (auto localMethod : mLocalMethodGraveyard)
{
if ((localMethod->mMethodInstanceGroup != NULL) && (localMethod->mMethodInstanceGroup->mRefCount > 0))
bool inCEMachine = false;
if (localMethod->mMethodInstanceGroup != NULL)
{
if ((localMethod->mMethodInstanceGroup->mDefault != NULL) && (localMethod->mMethodInstanceGroup->mDefault->mInCEMachine))
inCEMachine = true;
if (localMethod->mMethodInstanceGroup->mMethodSpecializationMap != NULL)
{
for (auto& kv : *localMethod->mMethodInstanceGroup->mMethodSpecializationMap)
if (kv.mValue->mInCEMachine)
inCEMachine = true;
}
}
if (inCEMachine)
{
localMethod->mMethodInstanceGroup->mOwner->mOwnedLocalMethods.Add(localMethod);
}
else if ((localMethod->mMethodInstanceGroup != NULL) && (localMethod->mMethodInstanceGroup->mRefCount > 0))
{
localMethod->Dispose();
survivingLocalMethods.push_back(localMethod);

View file

@ -861,8 +861,10 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
methodDef->mIsNoReturn = true;
else if (typeRefName == "SkipCall")
methodDef->mIsSkipCall = true;
else if (typeRefName == "ConstEval")
methodDef->mIsConstEval = true;
else if (typeRefName == "Comptime")
{
methodDef->mHasComptime = true;
}
else if (typeRefName == "NoShow")
methodDef->mIsNoShow = true;
else if (typeRefName == "NoDiscard")
@ -883,6 +885,10 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
methodDef->mCommutableKind = BfCommutableKind_Forward;
}
}
else if (typeRefName == "OnCompile")
{
mCurTypeDef->mHasCEOnCompile = true;
}
}
attributes = attributes->mNextAttribute;
@ -927,6 +933,7 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration)
Fail("Const properties are not allowed", propertyDeclaration->mConstSpecifier);
}
if (mSignatureHashCtx != NULL)
HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
BfPropertyDef* propertyDef = new BfPropertyDef();
@ -956,6 +963,7 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration)
if (propertyDeclaration->mDefinitionBlock == NULL) // To differentiate between autocompleting partial property if it transitions to a field
{
//mCurTypeDef->mSignatureHash = HashString("nullprop", mCurTypeDef->mSignatureHash);
if (mSignatureHashCtx != NULL)
mSignatureHashCtx->MixinStr("nullprop");
}
@ -984,11 +992,14 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration)
}
for (auto methodDeclaration : propertyDeclaration->mMethods)
{
if (mSignatureHashCtx != NULL)
{
HashNode(*mSignatureHashCtx, methodDeclaration->mAttributes);
HashNode(*mSignatureHashCtx, methodDeclaration->mProtectionSpecifier);
HashNode(*mSignatureHashCtx, methodDeclaration->mNameNode);
HashNode(*mSignatureHashCtx, methodDeclaration->mMutSpecifier);
}
if (!wantsBody)
continue;
@ -1141,6 +1152,7 @@ void BfDefBuilder::Visit(BfFieldDeclaration* fieldDeclaration)
fieldDef->mInitializer = fieldDeclaration->mInitializer;
//mCurTypeDef->mSignatureHash = HashNode(fieldDeclaration, mCurTypeDef->mSignatureHash);
if (mSignatureHashCtx != NULL)
HashNode(*mSignatureHashCtx, fieldDeclaration);
}
@ -1918,26 +1930,35 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
bool hasCtor = false;
bool needsDefaultCtor = (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (!mCurTypeDef->mIsStatic) && (!isAlias);
bool hasDefaultCtor = false;
bool hasStaticCtor = false;
bool hasDtor = false;
bool hasStaticDtor = false;
bool hasMarkMethod = false;
bool hasStaticMarkMethod = false;
bool hasDynamicCastMethod = false;
bool hasToStringMethod = false;
BfMethodDef* ctorClear = NULL;
BfMethodDef* staticCtor = NULL;
BfMethodDef* dtor = NULL;
BfMethodDef* staticDtor = NULL;
BfMethodDef* markMethod = NULL;
BfMethodDef* staticMarkMethod = NULL;
BfMethodDef* dynamicCastMethod = NULL;
BfMethodDef* toStringMethod = NULL;
bool needsEqualsMethod = ((mCurTypeDef->mTypeCode == BfTypeCode_Struct) || (mCurTypeDef->mTypeCode == BfTypeCode_Enum)) && (!mCurTypeDef->mIsStatic);
bool hasEqualsMethod = false;
BfMethodDef* equalsMethod = NULL;
BfMethodDef* strictEqualsMethod = NULL;
bool needsStaticInit = false;
for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
{
auto method = mCurTypeDef->mMethods[methodIdx];
auto _SetMethod = [&](BfMethodDef*& setMethodDef, BfMethodDef* methodDef)
{
if ((setMethodDef != NULL) && (setMethodDef->mMethodDeclaration == NULL))
setMethodDef->mProtection = BfProtection_Hidden;
setMethodDef = methodDef;
};
if (method->mMethodType == BfMethodType_Ctor)
{
if (method->mIsStatic)
{
if (hasStaticCtor)
if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL))
{
Fail("Only one static constructor is allowed", method->mMethodDeclaration);
method->mIsStatic = false;
@ -1950,9 +1971,9 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
}
if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC)
hasStaticMarkMethod = true;
_SetMethod(staticMarkMethod, method);
hasStaticCtor = true;
_SetMethod(staticCtor, method);
}
else
{
@ -1997,6 +2018,10 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
}
}
}
if (method->mMethodType == BfMethodType_CtorClear)
{
ctorClear = method;
}
else if (method->mMethodType == BfMethodType_Init)
{
if (method->mIsStatic)
@ -2006,22 +2031,22 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
{
if (method->mIsStatic)
{
if (hasStaticDtor)
if ((staticDtor != NULL) && (staticDtor->mMethodDeclaration != NULL))
{
Fail("Only one static constructor is allowed", method->mMethodDeclaration);
method->mIsStatic = false;
}
hasStaticDtor = true;
_SetMethod(staticDtor, method);
}
else
{
if (hasDtor)
if ((dtor != NULL) && (dtor->mMethodDeclaration != NULL))
{
Fail("Only one destructor is allowed", method->mMethodDeclaration);
method->mIsStatic = false;
}
hasDtor = true;
_SetMethod(dtor, method);
}
if (method->mParams.size() != 0)
@ -2032,16 +2057,16 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if (method->mIsStatic)
{
if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC)
hasStaticMarkMethod = true;
_SetMethod(staticMarkMethod, method);
}
else
{
if (method->mName == BF_METHODNAME_MARKMEMBERS)
hasMarkMethod = true;
_SetMethod(markMethod, method);
if (method->mName == BF_METHODNAME_DYNAMICCAST)
hasDynamicCastMethod = true;
_SetMethod(dynamicCastMethod, method);
if (method->mName == BF_METHODNAME_TO_STRING)
hasToStringMethod = true;
_SetMethod(toStringMethod, method);
}
}
else if ((method->mMethodType == BfMethodType_Operator) &&
@ -2056,7 +2081,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if ((method->mParams[0]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()) &&
(method->mParams[1]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()))
{
hasEqualsMethod = true;
_SetMethod(equalsMethod, method);
}
}
}
@ -2121,7 +2146,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
}
}
bool needsDynamicCastMethod = !hasDynamicCastMethod;
bool needsDynamicCastMethod = dynamicCastMethod == NULL;
if (mCurTypeDef->mIsFunction)
{
@ -2131,24 +2156,24 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
needsDynamicCastMethod = false;
}
if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic))
if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic) && (ctorClear == NULL))
{
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "");
methodDef->mIsMutating = true;
}
if ((needsDtor) && (!hasDtor))
if ((needsDtor) && (dtor == NULL))
{
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, false, "");
BF_ASSERT(mCurTypeDef->mDtorDef == methodDef);
}
if ((needsStaticDtor) && (!hasStaticDtor))
if ((needsStaticDtor) && (staticDtor == NULL))
{
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, true, "");
}
if ((needsStaticInit) && (!hasStaticCtor))
if ((needsStaticInit) && (staticCtor == NULL))
{
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "");
}
@ -2202,7 +2227,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if (mCurTypeDef->mTypeCode != BfTypeCode_Interface)
{
if ((hasStaticField) && (!hasStaticMarkMethod))
if ((hasStaticField) && (staticMarkMethod == NULL))
{
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC);
methodDef->mIsNoReflect = true;
@ -2214,7 +2239,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mIsNoReflect = true;
}
if ((hasNonStaticField) && (!hasMarkMethod))
if ((hasNonStaticField) && (markMethod == NULL))
{
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS);
methodDef->mIsVirtual = true;
@ -2225,7 +2250,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
}
}
if (hasToStringMethod)
if (toStringMethod != NULL)
wantsToString = false;
if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (!isPayloadEnum))
@ -2292,7 +2317,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
mCurTypeDef->mHasOverrideMethods = true;
}
if ((needsEqualsMethod) && (!hasEqualsMethod))
if ((needsEqualsMethod) && (equalsMethod == NULL))
{
auto methodDef = new BfMethodDef();
mCurTypeDef->mMethods.push_back(methodDef);

View file

@ -799,7 +799,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
SET_BETTER_OR_WORSE((!isUnspecializedParam) && (!paramType->IsVar()),
(!isPrevUnspecializedParam) && (!prevParamType->IsVar()));
if ((!isBetter) && (!isWorse) && (!isUnspecializedParam) && (!isPrevUnspecializedParam))
// Why did we have this !isUnspecializedParam check? We need the 'canCast' logic still
if ((!isBetter) && (!isWorse) /*&& (!isUnspecializedParam) && (!isPrevUnspecializedParam)*/)
{
SET_BETTER_OR_WORSE((paramType != NULL) && (!paramType->IsUnspecializedType()),
(prevParamType != NULL) && (!prevParamType->IsUnspecializedType()));
@ -851,7 +852,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
}
}
if ((!isBetter) & (!isWorse) && (paramsEquivalent))
if ((!isBetter) && (!isWorse) && (paramsEquivalent))
{
if ((origParamType != origPrevParamType) && (paramWasConstExpr) && (!prevParamWasConstExpr))
betterByConstExprParam = true;
@ -2698,21 +2699,21 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete()
return mModule->mCompiler->mResolvePassData->mAutoComplete;
}
bool BfExprEvaluator::IsConstEval()
bool BfExprEvaluator::IsComptime()
{
return (mModule->mIsConstModule) || ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0);
return (mModule->mIsComptimeModule) || ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0);
}
bool BfExprEvaluator::IsConstEvalEntry()
bool BfExprEvaluator::IsComptimeEntry()
{
if (mModule->mIsConstModule)
if (mModule->mIsComptimeModule)
return false;
return ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0);
return ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0);
}
int BfExprEvaluator::GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic)
{
if (IsConstEval())
if (IsComptime())
return -1;
return methodInstance->GetStructRetIdx(forceStatic);
}
@ -3333,7 +3334,7 @@ void BfExprEvaluator::Visit(BfLiteralExpression* literalExpr)
void BfExprEvaluator::Visit(BfStringInterpolationExpression* stringInterpolationExpression)
{
if (IsConstEvalEntry())
if (IsComptimeEntry())
{
mModule->Fail("Const evaluation of string interpolation not allowed", stringInterpolationExpression);
}
@ -5074,6 +5075,19 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
BF_ASSERT(!methodInstance->mDisallowCalling);
if ((mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCompiler->mResolvePassData->mAutoComplete != NULL))
{
bool wantQuickEval = true;
if (IsComptime())
{
auto autoComplete = mModule->mCompiler->mResolvePassData->mAutoComplete;
wantQuickEval =
((autoComplete->mResolveType != BfResolveType_Autocomplete) &&
(autoComplete->mResolveType != BfResolveType_Autocomplete_HighPri) &&
(autoComplete->mResolveType != BfResolveType_GetResultString));
}
if (wantQuickEval)
{
// In an autocomplete pass we may have stale method references that need to be resolved
// in the full classify pass, and in the full classify pass while just refreshing internals, we
@ -5089,7 +5103,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
}
}
if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0)
if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
{
if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
{
@ -5113,6 +5127,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
result = _GetDefaultReturnValue();
return result;
}
}
bool forceBind = false;
@ -5120,7 +5135,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{
bool doConstReturn = false;
if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0)
if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
{
if (mFunctionBindResult != NULL)
{
@ -5134,6 +5149,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{
doConstReturn = true;
}
else if (((methodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) && (!mModule->mIsComptimeModule))
{
// This either generated an error already or this is just the non-const type check pass for a comptime-only method
doConstReturn = true;
}
else
{
CeEvalFlags evalFlags = CeEvalFlags_None;
@ -5143,9 +5163,20 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
BF_ASSERT(!constRet.mType->IsVar());
return constRet;
}
if (mModule->mCompiler->mFastFinish)
{
if ((mModule->mCurMethodInstance == NULL) || (!mModule->mCurMethodInstance->mIsAutocompleteMethod))
{
// We didn't properly resolve this so queue for a rebuild later
mModule->DeferRebuildType(mModule->mCurTypeInstance);
}
doConstReturn = true;
}
}
else if (mModule->mIsConstModule)
}
else if (mModule->mIsComptimeModule)
{
if (methodInstance->mIsUnspecialized)
{
@ -5206,7 +5237,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface())
{
if (mModule->mIsConstModule)
if (mModule->mIsComptimeModule)
{
funcCallInst = mModule->mBfIRBuilder->ConstEval_GetInterfaceFunc(irArgs[0], methodInstance->mMethodInstanceGroup->mOwner->mTypeId, methodInstance->mMethodDef->mIdx, funcPtrType1);
}
@ -5226,7 +5257,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr);
}
}
else if (mModule->mIsConstModule)
else if (mModule->mIsComptimeModule)
{
funcCallInst = mModule->mBfIRBuilder->ConstEval_GetVirtualFunc(irArgs[0], methodInstance->mVirtualTableIdx, funcPtrType1);
}
@ -5323,7 +5354,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (irArgs.size() != 0)
{
auto targetType = methodInstance->mMethodInstanceGroup->mOwner;
if ((targetType->IsValueType()) && (targetType->IsSplattable()) && (!methodDef->HasNoThisSplat()) && (!IsConstEval()))
if ((targetType->IsValueType()) && (targetType->IsSplattable()) && (!methodDef->HasNoThisSplat()) && (!IsComptime()))
mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, BfTypedValueKind_SplatHead);
else
mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, targetType->IsComposite() ? BfTypedValueKind_Addr : BfTypedValueKind_Value);
@ -5484,7 +5515,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
mModule->PopulateType(paramType, BfPopulateType_Data);
auto typeInst = paramType->ToTypeInstance();
if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsConstEval()))
if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsComptime()))
{
// We're splatting
}
@ -5527,7 +5558,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
doingThis = false;
continue;
}
bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsConstEval()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsComptime()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
if (isSplatted)
{
BfTypeUtils::SplatIterate(_HandleParamType, paramType);
@ -5561,7 +5592,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
continue;
}
if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsConstEval()))
if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsComptime()))
{
BfTypeUtils::SplatIterate(_HandleParamType, paramType);
paramIdx++;
@ -5614,7 +5645,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{
BfTypeCode loweredRetType = BfTypeCode_None;
BfTypeCode loweredRetType2 = BfTypeCode_None;
if ((!IsConstEval()) && (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2)))
if ((!IsComptime()) && (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2)))
{
auto retVal = mModule->CreateAlloca(methodInstance->mReturnType);
BfIRType loweredIRType = mModule->GetIRLoweredType(loweredRetType, loweredRetType2);
@ -5780,7 +5811,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
return;
bool wantSplat = false;
if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsConstEval()))
if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime()))
{
disableLowering = true;
auto argTypeInstance = argVal.mType->ToTypeInstance();
@ -5801,7 +5832,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
{
if (argVal.mType->IsComposite())
{
if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0)
if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
{
// Const eval entry - we want any incoming consts as they are
}
@ -5812,7 +5843,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
else
argVal = mModule->MakeAddressable(argVal);
if ((!IsConstEval()) && (!disableLowering) && (!isIntrinsic))
if ((!IsComptime()) && (!disableLowering) && (!isIntrinsic))
{
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
@ -5906,7 +5937,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
auto owner = methodInstance->GetOwner();
bool allowThisSplatting;
if (mModule->mIsConstModule)
if (mModule->mIsComptimeModule)
allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType();
else
allowThisSplatting = methodInstance->AllowsSplatting(-1);
@ -6210,7 +6241,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
}
else
{
wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsConstEval());
wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsComptime());
if (methodInstance->IsImplicitCapture(paramIdx))
{
auto paramType = methodInstance->GetParamType(paramIdx);
@ -6275,7 +6306,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (methodDef->mMethodType == BfMethodType_Extension)
numElements++;
if (IsConstEvalEntry())
if (IsComptimeEntry())
{
if ((wantType->IsArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
{
@ -6694,7 +6725,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
else
{
// We need to make a temp and get the addr of that
if ((!wantsSplat) && (!argValue.IsValuelessType()) && (!argValue.IsAddr()) && (!IsConstEvalEntry()))
if ((!wantsSplat) && (!argValue.IsValuelessType()) && (!argValue.IsAddr()) && (!IsComptimeEntry()))
{
argValue = mModule->MakeAddressable(argValue);
}
@ -6714,7 +6745,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
{
if (argValue)
{
if (IsConstEvalEntry())
if (IsComptimeEntry())
{
auto constant = mModule->mBfIRBuilder->GetConstant(expandedParamsArray.mValue);
BF_ASSERT(constant->mConstType == BfConstType_Agg);
@ -8592,11 +8623,24 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
{
mModule->mAttributeState->mUsed = true;
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval);
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
}
else if (moduleMethodInstance.mMethodInstance->mMethodDef->mIsConstEval)
else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0)
{
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval);
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
}
else if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_Comptime) != 0) && (!mModule->mIsComptimeModule))
{
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
}
if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) &&
((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) &&
(mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None) &&
(!mModule->mIsComptimeModule))
{
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags &~ BfEvalExprFlags_Comptime);
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
}
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, bypassVirtual, argValues.mResolvedArgs, &argCascade, skipThis);
@ -11314,7 +11358,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
{
auto paramType = methodInstance->GetParamType(paramIdx);
if ((paramType->IsSplattable()) && (!IsConstEval()))
if ((paramType->IsSplattable()) && (!IsComptime()))
{
BfTypeUtils::SplatIterate([&](BfType* checkType) { irArgs.push_back(mModule->mBfIRBuilder->GetArgument(argIdx++)); }, paramType);
}
@ -13180,7 +13224,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
// Actually leave it alone?
if ((isUninit) &&
((mModule->IsOptimized()) || (mModule->mIsConstModule) || (mModule->mBfIRBuilder->mIgnoreWrites)))
((mModule->IsOptimized()) || (mModule->mIsComptimeModule) || (mModule->mBfIRBuilder->mIgnoreWrites)))
return;
bool doClear = true;
@ -13564,7 +13608,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign);
}
if (((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) && (mModule->mCompiler->mCEMachine != NULL))
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCEMachine != NULL))
{
mModule->mCompiler->mCEMachine->SetAppendAllocInfo(mModule, allocValue, appendSizeValue);
}
@ -13615,7 +13659,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
mModule->AssertErrorState();
}
else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) == 0)
else if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) == 0)
{
SizedArray<BfIRValue, 1> irArgs;
irArgs.push_back(mResult.mValue);
@ -13623,7 +13667,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
}
if ((!mModule->mIsConstModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck))
if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck))
{
BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers");
BF_ASSERT(markMethod != NULL);
@ -13693,7 +13737,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
}
if (((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) && (mModule->mCompiler->mCEMachine != NULL))
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCEMachine != NULL))
{
mModule->mCompiler->mCEMachine->ClearAppendAllocInfo();
}
@ -13887,7 +13931,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
if ((target.mType->IsStruct()) && (!target.IsAddr()))
{
if (IsConstEvalEntry())
if (IsComptimeEntry())
return target;
target = mModule->MakeAddressable(target);
}
@ -13923,7 +13967,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
auto ptrType = mModule->CreatePointerType(primStructType);
target = BfTypedValue(mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->MapType(ptrType)), primStructType, true);
}
else if ((primStructType->IsSplattable()) && (target.IsSplat()) && (!IsConstEval()))
else if ((primStructType->IsSplattable()) && (target.IsSplat()) && (!IsComptime()))
{
target.mType = primStructType;
target.mKind = BfTypedValueKind_SplatHead;
@ -15739,7 +15783,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
int methodCount = 0;
bool mayBeSkipCall = false;
bool mayBeConstEvalCall = false;
bool mayBeComptimeCall = false;
if (thisValue.mType != NULL)
{
if (thisValue.mType->IsAllocType())
@ -15757,8 +15801,8 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
{
if (methodDef->mIsSkipCall)
mayBeSkipCall = true;
if (methodDef->mIsConstEval)
mayBeConstEvalCall = true;
if (methodDef->mHasComptime)
mayBeComptimeCall = true;
methodDef = methodDef->mNextWithSameName;
}
}
@ -15784,7 +15828,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
BfResolveArgsFlags resolveArgsFlags = (BfResolveArgsFlags)(BfResolveArgsFlag_DeferFixits | BfResolveArgsFlag_AllowUnresolvedTypes);
resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamEval);
if ((mayBeSkipCall) || (mayBeConstEvalCall))
if ((mayBeSkipCall) || (mayBeComptimeCall))
resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamValues);
static int sCallIdx = 0;
@ -15810,7 +15854,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
}
}
if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0))
if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0))
mModule->Fail("Cascade operator cannot be used in const evaluation", cascadeOperatorToken);
SetAndRestoreValue<bool> prevUsedAsStatement(mUsedAsStatement, mUsedAsStatement || isCascade);
@ -16080,6 +16124,10 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
while (checkTypeInst != NULL)
{
mModule->PopulateType(checkTypeInst, BfPopulateType_DataAndMethods);
BF_ASSERT((checkTypeInst->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || (mModule->mCompiler->IsAutocomplete()));
if (checkTypeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotted)
break;
for (auto& iface : checkTypeInst->mInterfaces)
{
@ -18735,7 +18783,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
}
}
}
else if (((mModule->HasCompiledOutput()) || (mModule->mIsConstModule)) &&
else if (((mModule->HasCompiledOutput()) || (mModule->mIsComptimeModule)) &&
(wantsChecks))
{
if (checkedKind == BfCheckedKind_NotSet)
@ -18767,7 +18815,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
OutputDebugStrF("-OOB %d %d\n", oobFunc.mFunc.mId, oobFunc.mFunc.mFlags);
}*/
if (mModule->mIsConstModule)
if (mModule->mIsComptimeModule)
mModule->mCompiler->mCEMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc);
SizedArray<BfIRValue, 1> args;

View file

@ -390,8 +390,8 @@ public:
void FinishExpressionResult();
virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode);
BfAutoComplete* GetAutoComplete();
bool IsConstEval();
bool IsConstEvalEntry();
bool IsComptime();
bool IsComptimeEntry();
int GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic = false);
BfTypedValue SetupNullConditional(BfTypedValue target, BfTokenNode* dotToken);
void Evaluate(BfAstNode* astNode, bool propogateNullConditional = false, bool ignoreNullConditional = false, bool allowSplat = true);

View file

@ -634,6 +634,12 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
auto typeOf = (BfTypeOf_Const*)fromConst;
return CreateTypeOf(typeOf->mType);
}
else if (fromConst->mConstType == BfConstType_TypeOf_WithData)
{
auto typeOf = (BfTypeOf_WithData_Const*)fromConst;
auto dataConstant = fromHolder->GetConstant(typeOf->mTypeData);
return CreateTypeOf(typeOf->mType, CreateConst(dataConstant, fromHolder));
}
else if (fromConst->mConstType == BfConstType_AggZero)
{
auto aggZero = (BfConstant*)fromConst;
@ -791,6 +797,19 @@ BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type)
return irValue;
}
BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type, BfIRValue typeData)
{
BfTypeOf_WithData_Const* typeOf = mTempAlloc.Alloc<BfTypeOf_WithData_Const>();
typeOf->mConstType = BfConstType_TypeOf_WithData;
typeOf->mType = type;
typeOf->mTypeData = typeData;
auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(typeOf));
#ifdef CHECK_CONSTHOLDER
irValue.mHolder = this;
#endif
return irValue;
}
BfIRValue BfIRConstHolder::GetUndefConstValue(BfIRType irType)
{
auto constUndef = mTempAlloc.Alloc<BfConstantUndef>();
@ -1950,10 +1969,17 @@ void BfIRBuilder::Write(const BfIRValue& irValue)
Write(constant->mInt64);
}
break;
case (int)BfConstType_Undef:
case (int)BfConstType_TypeOf:
{
auto undefConst = (BfConstantUndef*)constant;
Write(undefConst->mType);
auto typeofConst = (BfTypeOf_Const*)constant;
Write(MapType(typeofConst->mType, BfIRPopulateType_Identity));
}
break;
case (int)BfConstType_TypeOf_WithData:
{
auto typeofConst = (BfTypeOf_WithData_Const*)constant;
Write(MapType(typeofConst->mType, BfIRPopulateType_Identity));
Write(typeofConst->mTypeData);
}
break;
default:
@ -4476,6 +4502,12 @@ BfIRValue BfIRBuilder::CreateGlobalStringPtr(const StringImpl& str)
return retVal;
}
void BfIRBuilder::SetReflectTypeData(BfIRType type, BfIRValue globalVar)
{
BfIRValue retVal = WriteCmd(BfIRCmd_SetReflectTypeData, type, globalVar);
NEW_CMD_INSERTED_IRVALUE;
}
BfIRBlock BfIRBuilder::CreateBlock(const StringImpl& name, bool addNow)
{
if (addNow)

View file

@ -120,6 +120,7 @@ enum BfConstType
BfConstType_PtrToInt,
BfConstType_IntToPtr,
BfConstType_TypeOf,
BfConstType_TypeOf_WithData,
BfConstType_AggZero,
BfConstType_Agg,
BfConstType_ArrayZero,
@ -235,6 +236,7 @@ enum BfIRCmd : uint8
BfIRCmd_GlobalVar_SetAlignment,
BfIRCmd_GlobalVar_SetStorageKind,
BfIRCmd_GlobalStringPtr,
BfIRCmd_SetReflectTypeData,
BfIRCmd_CreateBlock,
BfIRCmd_MaybeChainNewBlock,
@ -771,6 +773,14 @@ struct BfTypeOf_Const
{
BfConstType mConstType;
BfType* mType;
BfIRValue mTypeData;
};
struct BfTypeOf_WithData_Const
{
BfConstType mConstType;
BfType* mType;
BfIRValue mTypeData;
};
struct BfConstant
@ -906,6 +916,7 @@ public:
BfIRValue CreateConstArrayZero(BfIRType type, int count);
BfIRValue CreateConstArrayZero(int count);
BfIRValue CreateTypeOf(BfType* type);
BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData);
BfIRValue GetUndefConstValue(BfIRType type);
};
@ -1199,6 +1210,7 @@ public:
void GlobalVar_SetAlignment(BfIRValue globalVar, int alignment);
void GlobalVar_SetStorageKind(BfIRValue globalVar, BfIRStorageKind storageKind);
BfIRValue CreateGlobalStringPtr(const StringImpl& str);
void SetReflectTypeData(BfIRType type, BfIRValue globalVar);
BfIRBlock CreateBlock(const StringImpl& name, bool addNow = false);
BfIRBlock MaybeChainNewBlock(const StringImpl& name); // Creates new block if current block isn't empty

View file

@ -941,6 +941,21 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
llvmValue = llvm::UndefValue::get(type);
return;
}
else if (constType == BfConstType_TypeOf)
{
CMD_PARAM(llvm::Type*, type);
llvmValue = mReflectDataMap[type];
BF_ASSERT(llvmValue != NULL);
return;
}
else if (constType == BfConstType_TypeOf_WithData)
{
CMD_PARAM(llvm::Type*, type);
CMD_PARAM(llvm::Value*, value);
mReflectDataMap[type] = value;
llvmValue = value;
return;
}
bool isSigned;
llvm::Type* llvmConstType = GetLLVMType(typeCode, isSigned);
@ -2266,6 +2281,13 @@ void BfIRCodeGen::HandleNextCmd()
SetResult(curId, mIRBuilder->CreateGlobalStringPtr(llvm::StringRef(str.c_str(), str.length())));
}
break;
case BfIRCmd_SetReflectTypeData:
{
CMD_PARAM(llvm::Type*, type);
CMD_PARAM(llvm::Value*, value);
mReflectDataMap[type] = value;
}
break;
case BfIRCmd_CreateBlock:
{
CMD_PARAM(String, name);

View file

@ -108,6 +108,7 @@ public:
Dictionary<llvm::Function*, int> mIntrinsicReverseMap;
Array<llvm::Constant*> mConfigConsts32;
Array<llvm::Constant*> mConfigConsts64;
Dictionary<llvm::Type*, llvm::Value*> mReflectDataMap;
public:
void InitTarget();

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,7 @@ NS_BF_BEGIN
class BfType;
class BfResolvedType;
class BfExprEvaluator;
class CeEmitContext;
enum BfPopulateType
{
@ -71,7 +72,7 @@ enum BfEvalExprFlags
BfEvalExprFlags_AllowNonConst = 0x10000,
BfEvalExprFlags_StringInterpolateFormat = 0x20000,
BfEvalExprFlags_NoLookupError = 0x40000,
BfEvalExprFlags_ConstEval = 0x80000,
BfEvalExprFlags_Comptime = 0x80000,
BfEvalExprFlags_InCascade = 0x100000,
};
@ -1450,7 +1451,7 @@ public:
bool mWantsIRIgnoreWrites;
bool mHasGenericMethods;
bool mIsSpecialModule; // vdata, unspecialized, external
bool mIsConstModule;
bool mIsComptimeModule;
bool mIsScratchModule;
bool mIsSpecializedMethodModuleRoot;
bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module
@ -1686,6 +1687,7 @@ public:
BfInternalAccessSet* GetInternalAccessSet();
bool CheckInternalProtection(BfTypeDef* usingTypeDef);
void AddFailType(BfTypeInstance* typeInstance);
void DeferRebuildType(BfTypeInstance* typeInstance);
void MarkDerivedDirty(BfTypeInstance* typeInst);
void CheckAddFailType();
void PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
@ -1695,6 +1697,9 @@ public:
void SetTypeOptions(BfTypeInstance* typeInstance);
BfModuleOptions GetModuleOptions();
BfCheckedKind GetDefaultCheckedKind();
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode);
void ExecuteCEOnCompile(BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, CeEmitContext* ceEmitContext);
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
static BfModule* GetModuleFor(BfType* type);
void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance);

View file

@ -3,6 +3,7 @@
#include "BfCompiler.h"
#include "BfSystem.h"
#include "BfParser.h"
#include "BfReducer.h"
#include "BfCodeGen.h"
#include "BfExprEvaluator.h"
#include <fcntl.h>
@ -17,6 +18,7 @@
#include "BfFixits.h"
#include "BfIRCodeGen.h"
#include "BfDefBuilder.h"
#include "CeMachine.h"
//////////////////////////////////////////////////////////////////////////
@ -1931,6 +1933,177 @@ void BfModule::SetTypeOptions(BfTypeInstance* typeInstance)
typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true);
}
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode)
{
if (ceEmitContext->mEmitData.IsEmpty())
return;
int prevFailIdx = mCompiler->mPassInstance->mFailedIdx;
int prevWarnIdx = mCompiler->mPassInstance->mWarnIdx;
String src;
if (activeTypeDef->mEmitParser != NULL)
src += "\n\n";
src += "// Code emission in ";
src += ctxString;
src += "\n\n";
src += ceEmitContext->mEmitData;
ceEmitContext->mEmitData.Clear();
int startSrcIdx = 0;
if (activeTypeDef->mEmitParser == NULL)
{
BfParser* parser = new BfParser(mSystem, typeInstance->mTypeDef->mProject);
parser->mIsEmitted = true;
parser->mFileName = typeInstance->mTypeDef->mName->ToString();
BfLogSys(mSystem, "CreateParser (emit): %p\n", parser);
if (mCompiler->mIsResolveOnly)
parser->mFileName += "$EmitR$";
else
parser->mFileName += "$Emit$";
parser->mFileName += StrFormat("%d", typeInstance->mTypeId);
if (activeTypeDef->mPartialIdx != -1)
parser->mFileName + StrFormat(":%d", activeTypeDef->mPartialIdx);
parser->mFileName += StrFormat(".bf|%d", typeInstance->mRevision);
activeTypeDef->mEmitParser = parser;
parser->mRefCount++;
parser->SetSource(src.c_str(), src.mLength);
}
else
{
int idx = activeTypeDef->mEmitParser->AllocChars(src.mLength + 1);
memcpy((uint8*)activeTypeDef->mEmitParser->mSrc + idx, src.c_str(), src.mLength + 1);
activeTypeDef->mEmitParser->mSrcIdx = idx;
activeTypeDef->mEmitParser->mSrcLength = idx + src.mLength;
activeTypeDef->mEmitParser->mParserData->mSrcLength = activeTypeDef->mEmitParser->mSrcLength;
}
activeTypeDef->mEmitParser->Parse(mCompiler->mPassInstance);
activeTypeDef->mEmitParser->FinishSideNodes();
auto typeDeclaration = activeTypeDef->mEmitParser->mAlloc->Alloc<BfTypeDeclaration>();
BfReducer bfReducer;
bfReducer.mSource = activeTypeDef->mEmitParser;
bfReducer.mPassInstance = mCompiler->mPassInstance;
bfReducer.mAlloc = activeTypeDef->mEmitParser->mAlloc;
bfReducer.mSystem = mSystem;
bfReducer.mCurTypeDecl = typeDeclaration;
typeDeclaration->mDefineNode = activeTypeDef->mEmitParser->mRootNode;
bfReducer.HandleTypeDeclaration(typeDeclaration, NULL);
BfDefBuilder defBuilder(mSystem);
defBuilder.mCurTypeDef = typeInstance->mTypeDef;
defBuilder.DoVisitChild(typeDeclaration->mDefineNode);
defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum);
//
{
AutoCrit crit(mSystem->mDataLock);
mSystem->mParsers.Add(activeTypeDef->mEmitParser);
}
if ((prevFailIdx != mCompiler->mPassInstance->mFailedIdx) && (refNode != NULL))
Fail("Emitted code had errors", refNode);
else if ((prevWarnIdx != mCompiler->mPassInstance->mWarnIdx) && (refNode != NULL))
Warn(0, "Emitted code had warnings", refNode);
else if ((prevFailIdx != mCompiler->mPassInstance->mFailedIdx) ||
(prevWarnIdx != mCompiler->mPassInstance->mWarnIdx))
{
AddFailType(typeInstance);
}
}
void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, CeEmitContext* ceEmitContext)
{
if (!typeInstance->mTypeDef->mHasCEOnCompile)
return;
int methodCount = (int)typeInstance->mTypeDef->mMethods.size();
for (int methodIdx = 0; methodIdx < methodCount; methodIdx++)
{
auto methodDef = typeInstance->mTypeDef->mMethods[methodIdx];
auto methodDeclaration = BfNodeDynCast<BfMethodDeclaration>(methodDef->mMethodDeclaration);
if (methodDeclaration == NULL)
continue;
if (methodDeclaration->mAttributes == NULL)
continue;
auto customAttributes = GetCustomAttributes(methodDeclaration->mAttributes, BfAttributeTargets_Method);
defer({ delete customAttributes; });
auto onCompileAttribute = customAttributes->Get(mCompiler->mOnCompileAttributeTypeDef);
if (onCompileAttribute == NULL)
continue;
if (onCompileAttribute->mCtorArgs.size() < 1)
continue;
auto constant = typeInstance->mConstHolder->GetConstant(onCompileAttribute->mCtorArgs[0]);
if (constant == NULL)
continue;
if (onCompileKind != (BfCEOnCompileKind)constant->mInt32)
continue;
if (!methodDef->mIsStatic)
{
Fail("OnCompile methods must be static", methodDeclaration);
continue;
}
if (!methodDef->mParams.IsEmpty())
{
Fail("OnCompile methods cannot declare parameters", methodDeclaration);
continue;
}
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext);
if (onCompileKind == BfCEOnCompileKind_TypeInit)
{
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
}
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
if (!ceEmitContext->mEmitData.IsEmpty())
{
String ctxStr = "OnCompile execution of ";
ctxStr += MethodToString(methodInstance);
UpdateCEEmit(ceEmitContext, typeInstance, methodInstance->mMethodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode());
}
if (mCompiler->mCanceling)
{
DeferRebuildType(typeInstance);
}
}
}
void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers)
{
typeInstance->mTypeDef->ClearEmitted();
int startMethodCount = typeInstance->mTypeDef->mMethods.mSize;
int startFieldCount = typeInstance->mTypeDef->mFields.mSize;
CeEmitContext emitContext;
emitContext.mType = typeInstance;
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit, &emitContext);
if ((startMethodCount != typeInstance->mTypeDef->mMethods.mSize) ||
(startFieldCount != typeInstance->mTypeDef->mFields.mSize))
{
typeInstance->mTypeDef->ClearMemberSets();
hadNewMembers = true;
}
}
void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
{
auto typeInstance = resolvedTypeRef->ToTypeInstance();
@ -1991,7 +2164,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize;
}
BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()));
BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mTypeDef->mHasEmitMembers));
typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size());
for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++)
{
@ -2859,6 +3032,27 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (typeInstance->mTypeOptionsIdx == -2)
SetTypeOptions(typeInstance);
// if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit)
// {
// if (populateType <= BfPopulateType_AllowStaticMethods)
// return;
//
// auto refNode = typeDef->GetRefNode();
// Fail("OnCompile const evaluation creates a data dependency during TypeInit", refNode);
// mCompiler->mCEMachine->Fail("OnCompile const evaluation creates a data dependency during TypeInit");
// }
// else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
// {
// typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
// ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit);
//
// if (_CheckTypeDone())
// return;
//
// if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
// typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit;
// }
if (populateType <= BfPopulateType_AllowStaticMethods)
return;
@ -3156,6 +3350,44 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
}
}
}
if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit)
{
if (populateType <= BfPopulateType_AllowStaticMethods)
return;
String error = "OnCompile const evaluation creates a data dependency during TypeInit";
if (mCompiler->mCEMachine->mCurBuilder != NULL)
{
error += StrFormat(" during const-eval generation of '%s'", MethodToString(mCompiler->mCEMachine->mCurBuilder->mCeFunction->mMethodInstance).c_str());
}
auto refNode = typeDef->GetRefNode();
Fail(error, refNode);
if (mCompiler->mCEMachine->mCurFrame != NULL)
mCompiler->mCEMachine->Fail(*mCompiler->mCEMachine->mCurFrame, error);
else
mCompiler->mCEMachine->Fail(error);
}
else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
{
typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
bool hadNewMembers = false;
DoCEEmit(typeInstance, hadNewMembers);
if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit;
if (hadNewMembers)
{
typeInstance->mTypeDef->mHasEmitMembers = true;
DoPopulateType(resolvedTypeRef, populateType);
return;
}
if (_CheckTypeDone())
return;
}
}
if (_CheckTypeDone())
@ -3670,7 +3902,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
member->mRefCount++;
}
if (typeInstance->mDefineState < BfTypeDefineState_Defined)
{
typeInstance->mDefineState = BfTypeDefineState_Defined;
if (!typeInstance->IsBoxed())
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeDone, NULL);
}
if (typeInstance->mTypeFailed)
mHadBuildError = true;
@ -3832,7 +4069,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
int64 min = 0;
int64 max = 0;
bool isFirst = false;
bool isFirst = true;
if (typeInstance->mTypeInfoEx == NULL)
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
@ -4311,8 +4548,6 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
continue;
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_InWorkList)
continue;
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
continue;
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Referenced)
continue;
@ -4322,8 +4557,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
continue;
}
// This should still be set to the default value
BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) || (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl));
BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) ||
(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference));
if ((isBoxed) && (!methodDef->mIsVirtual))
{
@ -4352,8 +4588,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if ((methodDef->mName == BF_METHODNAME_DYNAMICCAST) && (typeInstance->IsValueType()))
continue; // This is just a placeholder for boxed types
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
bool doAlwaysInclude = false;
if (wantsOnDemandMethods)
{
@ -4453,8 +4688,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (!implRequired)
{
BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet);
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
{
if (!mIsScratchModule)
mOnDemandMethodCount++;
@ -4462,18 +4696,40 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (!declRequired)
{
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
continue;
}
else
{
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
}
VerifyOnDemandMethods();
}
else
{
doAlwaysInclude = true;
}
}
else
doAlwaysInclude = true;
if (doAlwaysInclude)
{
bool wasDeclared = (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference);
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
if (wasDeclared)
{
if (!mIsScratchModule)
mOnDemandMethodCount--;
if (methodInstanceGroup->mDefault != NULL)
AddMethodToWorkList(methodInstanceGroup->mDefault);
}
}
}
@ -5480,7 +5736,7 @@ BfPrimitiveType* BfModule::GetPrimitiveType(BfTypeCode typeCode)
BfIRType BfModule::GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2)
{
BF_ASSERT(!mIsConstModule);
BF_ASSERT(!mIsComptimeModule);
BF_ASSERT(loweredTypeCode != BfTypeCode_None);
if (loweredTypeCode2 == BfTypeCode_None)

View file

@ -341,6 +341,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
mAwaitingDelete = false;
mScanOnly = false;
mCompleteParse = false;
mIsEmitted = false;
mJumpTable = NULL;
mProject = bfProject;
mPassInstance = NULL;
@ -525,6 +526,8 @@ void BfParser::SetSource(const char* data, int length)
canCache = false;
if (mProject == NULL)
canCache = false;
if (mIsEmitted)
canCache = false;
uint64 cacheHash = 0;
if (canCache)
@ -3447,8 +3450,11 @@ void BfParser::Parse(BfPassInstance* passInstance)
{
BP_ZONE_F("BfParser::Parse %s", mFileName.c_str());
mSyntaxToken = BfSyntaxToken_None;
mPassInstance = passInstance;
int startIdx = mSrcIdx;
if (mUsingCache)
{
mRootNode = mParserData->mRootNode;
@ -3476,7 +3482,7 @@ void BfParser::Parse(BfPassInstance* passInstance)
mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first);
}
for (int i = 1; i < mJumpTableSize; i++)
for (int i = (startIdx / PARSER_JUMPTABLE_DIVIDE)+1; i < mJumpTableSize; i++)
if (mJumpTable[i].mCharIdx == 0)
mJumpTable[i] = mJumpTable[i - 1];
@ -3523,6 +3529,26 @@ void BfParser::Close()
}
}
void BfParser::HadSrcRealloc()
{
int jumpTableSize = ((mSrcAllocSize + 1) + PARSER_JUMPTABLE_DIVIDE - 1) / PARSER_JUMPTABLE_DIVIDE;
if (jumpTableSize > mJumpTableSize)
{
auto jumpTable = new BfLineStartEntry[jumpTableSize];
memset(jumpTable, 0, jumpTableSize * sizeof(BfLineStartEntry));
memcpy(jumpTable, mJumpTable, mJumpTableSize * sizeof(BfLineStartEntry));
delete mJumpTable;
mJumpTable = jumpTable;
mJumpTableSize = jumpTableSize;
mParserData->mJumpTable = mJumpTable;
mParserData->mJumpTableSize = mJumpTableSize;
}
}
void BfParser::GenerateAutoCompleteFrom(int srcPosition)
{
BfSourcePositionFinder posFinder(this, srcPosition);

View file

@ -157,6 +157,7 @@ public:
bool mQuickCompatMode;
bool mScanOnly;
bool mCompleteParse;
bool mIsEmitted;
BfLineStartEntry* mJumpTable;
int mJumpTableSize;
int mOrigSrcLength;
@ -231,6 +232,7 @@ public:
void Parse(BfPassInstance* passInstance);
int GetCharIdAtIndex(int findIndex);
virtual void Close() override;
virtual void HadSrcRealloc() override;
void GenerateAutoCompleteFrom(int srcPosition);

View file

@ -1143,7 +1143,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
BfTypeCode loweredReturnTypeCode = BfTypeCode_None;
BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None;
if ((!module->mIsConstModule) && (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2)))
if ((!module->mIsComptimeModule) && (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2)))
{
auto irReturnType = module->GetIRLoweredType(loweredReturnTypeCode, loweredReturnTypeCode2);
returnType = irReturnType;
@ -1153,7 +1153,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);
}
else if ((!module->mIsConstModule) && (GetStructRetIdx(forceStatic) != -1))
else if ((!module->mIsComptimeModule) && (GetStructRetIdx(forceStatic) != -1))
{
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);
@ -1210,11 +1210,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
{
checkType = checkType->GetUnderlyingType();
}
else if ((!module->mIsConstModule) && (checkType->IsSplattable()) && (AllowsSplatting(-1)))
else if ((!module->mIsComptimeModule) && (checkType->IsSplattable()) && (AllowsSplatting(-1)))
{
doSplat = true;
}
else if ((!module->mIsConstModule) && (!mMethodDef->mIsMutating) && (mCallingConvention == BfCallingConvention_Unspecified))
else if ((!module->mIsComptimeModule) && (!mMethodDef->mIsMutating) && (mCallingConvention == BfCallingConvention_Unspecified))
checkLowered = true;
}
else
@ -1227,11 +1227,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
{
checkType = checkType->GetUnderlyingType();
}
else if ((!module->mIsConstModule) && (checkType->IsSplattable()) && (AllowsSplatting(paramIdx)))
else if ((!module->mIsComptimeModule) && (checkType->IsSplattable()) && (AllowsSplatting(paramIdx)))
{
doSplat = true;
}
else if (!module->mIsConstModule)
else if (!module->mIsComptimeModule)
checkLowered = true;
}
@ -1311,7 +1311,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
paramIdx++; // Skip over the explicit 'this'
}
if ((!module->mIsConstModule) && (GetStructRetIdx(forceStatic) == 1))
if ((!module->mIsComptimeModule) && (GetStructRetIdx(forceStatic) == 1))
{
BF_SWAP(paramTypes[0], paramTypes[1]);
}
@ -1509,6 +1509,8 @@ BfTypeInstance::~BfTypeInstance()
delete methodInst;
for (auto operatorInfo : mOperatorInfo)
delete operatorInfo;
for (auto localMethod : mOwnedLocalMethods)
delete localMethod;
delete mHotTypeData;
delete mConstHolder;
}

View file

@ -416,7 +416,9 @@ enum BfTypeRebuildFlags
BfTypeRebuildFlag_UnderlyingTypeDeferred = 0x1000,
BfTypeRebuildFlag_TypeDataSaved = 0x2000,
BfTypeRebuildFlag_InTempPool = 0x4000,
BfTypeRebuildFlag_ResolvingBase = 0x8000
BfTypeRebuildFlag_ResolvingBase = 0x8000,
BfTypeRebuildFlag_InFailTypes = 0x10000,
BfTypeRebuildFlag_RebuildQueued = 0x20000,
};
class BfTypeDIReplaceCallback;
@ -427,7 +429,10 @@ enum BfTypeDefineState : uint8
BfTypeDefineState_Declared,
BfTypeDefineState_ResolvingBaseType,
BfTypeDefineState_HasInterfaces,
BfTypeDefineState_CETypeInit,
BfTypeDefineState_CEPostTypeInit,
BfTypeDefineState_Defined,
BfTypeDefineState_CEAfterFields,
BfTypeDefineState_DefinedAndMethodsSlotted,
};
@ -830,6 +835,7 @@ public:
bool mInCEMachine:1;
bool mIsDisposed:1;
BfMethodChainType mChainType;
BfComptimeFlags mComptimeFlags;
BfCallingConvention mCallingConvention;
BfMethodInstanceGroup* mMethodInstanceGroup;
BfMethodDef* mMethodDef;
@ -868,6 +874,7 @@ public:
mInCEMachine = false;
mIsDisposed = false;
mChainType = BfMethodChainType_None;
mComptimeFlags = BfComptimeFlag_None;
mCallingConvention = BfCallingConvention_Unspecified;
mMethodInstanceGroup = NULL;
mMethodDef = NULL;
@ -1792,6 +1799,7 @@ public:
Array<BfMethodInstance*> mInternalMethods;
Dictionary<BfTypeDef*, BfStaticSearch> mStaticSearchMap;
Dictionary<BfTypeDef*, BfInternalAccessSet> mInternalAccessMap;
Array<BfLocalMethod*> mOwnedLocalMethods; // Local methods in CEMachine
bool mHasStaticInitMethod;
bool mHasStaticDtorMethod;
bool mHasStaticMarkMethod;
@ -1969,7 +1977,7 @@ public:
bool IsAlwaysInclude();
bool HasBeenInstantiated() { return mHasBeenInstantiated || ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_AssumeInstantiated) != 0); }
bool IncludeAllMethods() { return ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_IncludeAllMethods) != 0); }
bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces; }
virtual void ReportMemory(MemReporter* memReporter) override;
};

View file

@ -91,6 +91,8 @@ int BfSource::AllocChars(int charCount)
BF_ASSERT(mSourceData->ToParser() != NULL);
mSourceData->mSrc = mSrc;
HadSrcRealloc();
}
int retVal = mSrcLength;

View file

@ -101,6 +101,7 @@ public:
virtual ~BfSource();
virtual BfParser* ToParser() { return NULL; }
virtual void HadSrcRealloc() {}
BfErrorNode* CreateErrorNode(BfAstNode* astNode);
void AddErrorNode(BfAstNode* astNode);

View file

@ -42,7 +42,7 @@ USING_NS_BF;
bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scopeData)
{
if ((((mCompiler->mIsResolveOnly) && (!mIsConstModule)) ||
if ((((mCompiler->mIsResolveOnly) && (!mIsComptimeModule)) ||
(mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL))
{
// For resolve entries, we only keep deferred blocks because we need to process them later so we can
@ -783,7 +783,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz
void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks)
{
if ((mCompiler->mIsResolveOnly) && (!mIsConstModule) && (deferredCallEntry.mHandlerCount > 0))
if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (deferredCallEntry.mHandlerCount > 0))
{
// We only want to process deferred blocks once, otherwise it could significantly slow down autocompletion
return;
@ -1770,7 +1770,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
initValue = LoadValue(initValue);
if (initValue.IsSplat())
{
BF_ASSERT(!mIsConstModule);
BF_ASSERT(!mIsComptimeModule);
if (!localDef->mAddr)
localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
AggregateSplatIntoAddr(initValue, localDef->mAddr);
@ -3944,7 +3944,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
allowPrivate = false;
}
if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
{
auto preDelete = GetInternalMethod((deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete");
SizedArray<BfIRValue, 4> llvmArgs;
@ -4001,7 +4001,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
}
else
{
if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsConstModule))
if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsComptimeModule))
{
SizedArray<BfIRValue, 4> llvmArgs;
llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType)));
@ -4958,12 +4958,12 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
BfType* origType;
BfExprEvaluator exprEvaluator(this);
bool alreadyWritten = false;
if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
exprEvaluator.mReceivingValue = &mCurMethodState->mRetVal;
if (mCurMethodInstance->mMethodDef->mIsReadOnly)
exprEvaluator.mAllowReadOnlyReference = true;
auto retValue = CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, expectingReturnType, BfEvalExprFlags_AllowRefExpr, &origType);
if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
alreadyWritten = exprEvaluator.mReceivingValue == NULL;
MarkScopeLeft(&mCurMethodState->mHeadScope);
@ -6453,7 +6453,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
auto retVal = exprEvaluator.CreateCall(&methodMatcher, itr);
if (exprEvaluator.mReceivingValue != NULL)
{
if (mIsConstModule)
if (mIsComptimeModule)
{
mBfIRBuilder->CreateStore(retVal.mValue, nextResult.mValue);
}
@ -6802,7 +6802,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt)
if (!customAllocator)
{
if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsConstModule))
if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsComptimeModule))
{
auto moduleMethodInstance = GetInternalMethod("Dbg_MarkObjectDeleted");
AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
@ -6819,7 +6819,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt)
auto moduleMethodInstance = GetMethodInstance(objectType, methodInstance->mMethodDef, BfTypeVector());
AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
{
auto moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), (deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete");
AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
@ -6831,7 +6831,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt)
{
val = LoadValue(val);
BfModuleMethodInstance moduleMethodInstance;
if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule))
if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Dbg_RawFree");
else
moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Free");

View file

@ -679,6 +679,42 @@ void BfTypeDef::FreeMembers()
mIsNextRevision = false;
}
void BfTypeDef::ClearEmitted()
{
for (auto& partial : mPartials)
partial->ClearEmitted();
if (mEmitParser != NULL)
{
mEmitParser->mRefCount--;
BF_ASSERT(mEmitParser->mRefCount >= 0);
mEmitParser = NULL;
}
if (mHasEmitMembers)
{
for (int methodIdx = (int)mMethods.size() - 1; methodIdx >= 0; methodIdx--)
{
auto methodDef = mMethods[methodIdx];
if ((methodDef->mMethodDeclaration != NULL) && (methodDef->mMethodDeclaration->IsEmitted()))
{
delete methodDef;
mMethods.RemoveAt(methodIdx);
}
}
for (int fieldIdx = (int)mFields.size() - 1; fieldIdx >= 0; fieldIdx--)
{
auto fieldDef = mFields[fieldIdx];
if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->IsEmitted()))
{
delete fieldDef;
mFields.RemoveAt(fieldIdx);
}
}
}
}
void BfTypeDef::PopulateMemberSets()
{
if ((!mMethodSet.IsEmpty()) || (!mFieldSet.IsEmpty()) || (!mPropertySet.IsEmpty()))
@ -721,6 +757,13 @@ void BfTypeDef::PopulateMemberSets()
}
}
void BfTypeDef::ClearMemberSets()
{
mMethodSet.Clear();
mFieldSet.Clear();
mPropertySet.Clear();
}
BfTypeDef::~BfTypeDef()
{
BfLogSysM("BfTypeDef::~BfTypeDef %08X\n", this);
@ -732,6 +775,12 @@ BfTypeDef::~BfTypeDef()
mSource->mRefCount--;
BF_ASSERT(mSource->mRefCount >= 0);
}
if (mEmitParser != NULL)
{
mEmitParser->mRefCount--;
BF_ASSERT(mEmitParser->mRefCount >= 0);
}
}
BfSource* BfTypeDef::GetLastSource()
@ -1533,6 +1582,8 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf
if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true))
return NULL;
mWarnIdx++;
TrimSourceRange(bfSource, srcIdx, srcLen);
BfError* errorVal = new BfError();
@ -1564,6 +1615,7 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf
BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning)
{
mWarnIdx++;
mLastWasAdded = false;
mLastWasDisplayed = (int)mErrors.size() <= sMaxDisplayErrors;
if (!mLastWasDisplayed)
@ -1577,6 +1629,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAs
{
BP_ZONE("BfPassInstance::Warn");
mWarnIdx++;
mLastWasAdded = false;
mLastWasDisplayed = (int)mErrors.size() <= sMaxErrors;
if (!mLastWasDisplayed)
@ -1638,9 +1691,9 @@ BfMoreInfo* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfS
return NULL;
}
BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info)
BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info, bool forceQueue)
{
if (!mLastWasDisplayed)
if ((!mLastWasDisplayed) || (forceQueue))
{
if (mLastWasAdded)
{
@ -2534,6 +2587,8 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
{
BfLogSys(this, "InjectNewRevision from %p (decl:%p) into %p (decl:%p)\n", typeDef->mNextRevision, typeDef->mNextRevision->mTypeDeclaration, typeDef, typeDef->mTypeDeclaration);
typeDef->ClearEmitted();
bool setDeclaringType = !typeDef->mIsCombinedPartial;
auto nextTypeDef = typeDef->mNextRevision;
@ -2663,6 +2718,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
typeDef->mIsConcrete = nextTypeDef->mIsConcrete;
typeDef->mIsStatic = nextTypeDef->mIsStatic;
typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor;
typeDef->mHasCEOnCompile = nextTypeDef->mHasCEOnCompile;
typeDef->mHasCtorNoBody = nextTypeDef->mHasCtorNoBody;
typeDef->mHasOverrideMethods = nextTypeDef->mHasOverrideMethods;
typeDef->mHasExtensionMethods = nextTypeDef->mHasExtensionMethods;
@ -2771,6 +2827,8 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody;
typeDef->mHasExtensionMethods = partialTypeDef->mHasExtensionMethods;
typeDef->mHasOverrideMethods = partialTypeDef->mHasOverrideMethods;
typeDef->mIsAlwaysInclude = partialTypeDef->mIsAlwaysInclude;
typeDef->mHasCEOnCompile = partialTypeDef->mHasCEOnCompile;
for (auto generic : partialTypeDef->mGenericParamDefs)
{
@ -2806,6 +2864,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mIsConcrete |= partialTypeDef->mIsConcrete;
typeDef->mIsStatic |= partialTypeDef->mIsStatic;
typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor;
typeDef->mHasCEOnCompile |= partialTypeDef->mHasCEOnCompile;
typeDef->mHasExtensionMethods |= partialTypeDef->mHasExtensionMethods;
typeDef->mHasOverrideMethods |= partialTypeDef->mHasOverrideMethods;
typeDef->mProtection = BF_MIN(typeDef->mProtection, partialTypeDef->mProtection);
@ -3237,12 +3296,12 @@ void BfSystem::RemoveOldParsers()
BfLogSys(this, "Deleting Old Parser: %p New Parser: %p\n", bfParser, bfParser->mNextRevision);
mParsers.RemoveAt(i);
i--;
mDataLock.Unlock();
delete bfParser;
mDataLock.Lock();
mParsers.erase(mParsers.begin() + i);
i--;
}
}
}

View file

@ -218,6 +218,13 @@ enum BfAlwaysIncludeFlags : uint8
BfAlwaysIncludeFlag_All = BfAlwaysIncludeFlag_Type | BfAlwaysIncludeFlag_IncludeAllMethods | BfAlwaysIncludeFlag_AssumeInstantiated
};
enum BfCEOnCompileKind : uint8
{
BfCEOnCompileKind_None,
BfCEOnCompileKind_TypeInit,
BfCEOnCompileKind_TypeDone
};
enum BfPlatformType
{
BfPlatformType_Unknown,
@ -740,6 +747,14 @@ enum BfCommutableKind : int8
BfCommutableKind_Reverse,
};
enum BfComptimeFlags : int8
{
BfComptimeFlag_None,
BfComptimeFlag_Comptime = 1,
BfComptimeFlag_OnlyFromComptime = 2,
BfComptimeFlag_ConstEval = 4
};
class BfMethodDef : public BfMemberDef
{
public:
@ -774,7 +789,7 @@ public:
bool mIsNoSplat;
bool mIsNoReflect;
bool mIsSkipCall;
bool mIsConstEval;
bool mHasComptime;
bool mIsOperator;
bool mIsExtern;
bool mIsNoDiscard;
@ -803,7 +818,7 @@ public:
mIsNoSplat = false;
mIsNoReflect = false;
mIsSkipCall = false;
mIsConstEval = false;
mHasComptime = false;
mIsOperator = false;
mIsExtern = false;
mIsNoDiscard = false;
@ -919,6 +934,7 @@ public:
BfProject* mProject;
BfTypeDeclaration* mTypeDeclaration;
BfSource* mSource;
BfParser* mEmitParser;
DefState mDefState;
Val128 mSignatureHash; // Data, methods, etc
Val128 mFullHash;
@ -966,6 +982,7 @@ public:
bool mIsAbstract;
bool mIsConcrete;
bool mIsStatic;
bool mHasCEOnCompile;
bool mHasAppendCtor;
bool mHasCtorNoBody;
bool mHasExtensionMethods;
@ -973,6 +990,7 @@ public:
bool mIsOpaque;
bool mIsNextRevision;
bool mInDeleteQueue;
bool mHasEmitMembers;
public:
BfTypeDef()
@ -996,6 +1014,7 @@ public:
mIsCombinedPartial = false;
mTypeDeclaration = NULL;
mSource = NULL;
mEmitParser = NULL;
mDefState = DefState_New;
mHash = 0;
mPartialIdx = -1;
@ -1005,6 +1024,7 @@ public:
mIsFunction = false;
mIsClosure = false;
mIsStatic = false;
mHasCEOnCompile = false;
mHasAppendCtor = false;
mHasCtorNoBody = false;
mHasExtensionMethods = false;
@ -1013,6 +1033,7 @@ public:
mPartialUsed = false;
mIsNextRevision = false;
mInDeleteQueue = false;
mHasEmitMembers = false;
mDupDetectedRevision = -1;
mNestDepth = 0;
mOuterType = NULL;
@ -1026,7 +1047,9 @@ public:
bool IsGlobalsContainer();
void Reset();
void FreeMembers();
void ClearEmitted();
void PopulateMemberSets();
void ClearMemberSets();
void RemoveGenericParamDef(BfGenericParamDef* genericParamDef);
int GetSelfGenericParamCount();
String ToString();
@ -1284,6 +1307,7 @@ public:
BfSystem* mSystem;
bool mTrimMessagesToCursor;
int mFailedIdx;
int mWarnIdx;
Dictionary<BfSourceData*, String> mSourceFileNameMap;
HashSet<BfErrorEntry> mErrorSet;
@ -1303,6 +1327,7 @@ public:
{
mTrimMessagesToCursor = false;
mFailedIdx = 0;
mWarnIdx = 0;
mSystem = bfSystem;
mLastWasDisplayed = false;
mLastWasAdded = false;
@ -1336,7 +1361,7 @@ public:
BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
BfMoreInfo* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None);
BfMoreInfo* MoreInfo(const StringImpl& info);
BfMoreInfo* MoreInfo(const StringImpl& info, bool forceQueue = false);
BfMoreInfo* MoreInfo(const StringImpl& info, BfAstNode* refNode);
BfMoreInfo* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode);

View file

@ -729,7 +729,6 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
if (mCeMachine->mStaticFieldMap.TryGetValue(globalVar->mName, &staticFieldInfoPtr))
{
CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr;
int* staticFieldTableIdxPtr = NULL;
if (mStaticFieldMap.TryAdd(globalVar, NULL, &staticFieldTableIdxPtr))
{
@ -1190,8 +1189,6 @@ void CeBuilder::Build()
bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation());
int dependentGenericStartIdx = 0;
if (methodInstance->mMethodInfoEx != NULL)
dependentGenericStartIdx = (int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size();
if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod))))
{
@ -2646,10 +2643,14 @@ CeMachine::CeMachine(BfCompiler* compiler)
mCurFunctionId = 0;
mRevisionExecuteTime = 0;
mCurTargetSrc = NULL;
mCurBuilder = NULL;
mPreparingFunction = NULL;
mCurEvalFlags = CeEvalFlags_None;
mCurFrame = NULL;
mCurModule = NULL;
mCurMethodInstance = NULL;
mCurExpectingType = NULL;
mCurEmitContext = NULL;
mHeap = NULL;
mStringCharsOffset = -1;
mAppendAllocInfo = NULL;
@ -2689,19 +2690,25 @@ CeMachine::~CeMachine()
BfError* CeMachine::Fail(const StringImpl& error)
{
auto bfError = mCurModule->Fail(StrFormat("Unable to const-evaluate %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc);
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
if (bfError == NULL)
return NULL;
mCompiler->mPassInstance->MoreInfo(error);
mCompiler->mPassInstance->MoreInfo(error, mCeModule->mCompiler->GetAutoComplete() != NULL);
return bfError;
}
BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
{
auto bfError = mCurModule->Fail(StrFormat("Unable to const-evaluate %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc);
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
if (bfError == NULL)
return NULL;
if ((mCurEvalFlags & CeEvalFlags_DeferIfNotOnlyError) != 0)
{
if (mCurModule->mHadBuildError)
bfError->mIsDeferred = true;
}
auto passInstance = mCompiler->mPassInstance;
for (int stackIdx = mCallStack.size(); stackIdx >= 0; stackIdx--)
@ -2748,7 +2755,7 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
contextMethodInstance = func->mCeFunctionInfo->mMethodInstance;
}
err += StrFormat("in const evaluation of ");
err += StrFormat("in comptime ");
//
{
@ -2766,7 +2773,7 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
if (emitEntry != NULL)
err += StrFormat(" at line% d:%d in %s", emitEntry->mLine + 1, emitEntry->mColumn + 1, ceFunction->mFiles[emitEntry->mFile].c_str());
auto moreInfo = passInstance->MoreInfo(err);
auto moreInfo = passInstance->MoreInfo(err, mCeModule->mCompiler->GetAutoComplete() != NULL);
if ((moreInfo != NULL) && (emitEntry != NULL))
{
BfErrorLocation* location = new BfErrorLocation();
@ -2785,7 +2792,7 @@ void CeMachine::Init()
mCeModule = new BfModule(mCompiler->mContext, "__constEval");
mCeModule->mIsSpecialModule = true;
//mCeModule->mIsScratchModule = true;
mCeModule->mIsConstModule = true;
mCeModule->mIsComptimeModule = true;
//mCeModule->mIsReified = true;
if (mCompiler->mIsResolveOnly)
mCeModule->mIsReified = true;
@ -2882,6 +2889,7 @@ addr_ce CeMachine::GetReflectType(int typeId)
if (bfType == NULL)
return 0;
if (bfType->mDefineState != BfTypeDefineState_CETypeInit)
mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
Dictionary<int, int> usedStringMap;
@ -2991,6 +2999,30 @@ void CeMachine::PrepareConstStructEntry(CeConstStructData& constEntry)
constEntry.mBindExecuteId = mExecuteId;
}
bool CeMachine::CheckMemory(addr_ce addr, int32 size)
{
if (((addr)-0x10000) + (size) > (mMemory.mSize - 0x10000))
return false;
return true;
}
bool CeMachine::GetStringFromStringView(addr_ce addr, StringImpl& str)
{
int ptrSize = mCeModule->mSystem->mPtrSize;
if (!CheckMemory(addr, ptrSize * 2))
return false;
addr_ce charsPtr = *(addr_ce*)(mMemory.mVals + addr);
int32 len = *(int32*)(mMemory.mVals + addr + ptrSize);
if (!CheckMemory(charsPtr, len))
return false;
str.Append((const char*)(mMemory.mVals + charsPtr), len);
return true;
}
BeContext* CeMachine::GetBeContext()
{
if (mCeModule == NULL)
@ -3016,6 +3048,12 @@ void CeMachine::CompileStarted()
}
}
void CeMachine::CompileDone()
{
// So things like delted local methods get recheckeds
mRevision++;
}
void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
{
ceFunctionInfo->mRefCount--;
@ -3257,6 +3295,13 @@ bool CeMachine::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
}
}
if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData))
{
auto constTypeOf = (BfTypeOf_Const*)constant;
CE_GETC(addr_ce) = GetReflectType(constTypeOf->mType->mTypeId);
return true;
}
return false;
}
@ -3489,7 +3534,6 @@ CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constV
return CeErrorKind_None;
}
#define CE_CREATECONST_CHECKPTR(PTR, SIZE) \
if ((((uint8*)(PTR) - memStart) - 0x10000) + (SIZE) > (memSize - 0x10000)) \
{ \
@ -3829,8 +3873,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
uint8* stackPtr = startStackPtr;
uint8* framePtr = startFramePtr;
bool needsFunctionIds = mCeModule->mSystem->mPtrSize != 8;
int32 ptrSize = mCeModule->mSystem->mPtrSize;
volatile bool* cancelPtr = &mCompiler->mCanceling;
volatile bool* fastFinishPtr = &mCompiler->mFastFinish;
volatile bool* cancelingPtr = &mCompiler->mCanceling;
auto _GetCurFrame = [&]()
{
@ -3973,12 +4019,30 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
handled = true;
return true;
}
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitDefinition)
{
int32 typeId = *(int32*)((uint8*)stackPtr);
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int32));
if ((mCurEmitContext == NULL) || (mCurEmitContext->mType->mTypeId != typeId))
{
_Fail("Missing emit context");
return false;
}
if (!GetStringFromStringView(strViewPtr, mCurEmitContext->mEmitData))
{
_Fail("Invalid StringView");
return false;
}
handled = true;
return true;
}
else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep)
{
int32 sleepMS = *(int32*)((uint8*)stackPtr);
while (sleepMS > 0)
{
if (*cancelPtr)
if (*fastFinishPtr)
break;
if (sleepMS > 200)
@ -4104,9 +4168,9 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (!checkFunction->mFailed)
return true;
auto error = Fail(_GetCurFrame(), "Method call failed");
auto error = Fail(_GetCurFrame(), StrFormat("Method call '%s' failed", mCeModule->MethodToString(checkFunction->mMethodInstance).c_str()));
if ((error != NULL) && (!checkFunction->mGenError.IsEmpty()))
mCompiler->mPassInstance->MoreInfo("Const Method Generation Error: " + checkFunction->mGenError);
mCompiler->mPassInstance->MoreInfo("Comptime method generation error: " + checkFunction->mGenError);
return false;
};
@ -4124,9 +4188,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
while (true)
{
if (*cancelPtr)
if (*fastFinishPtr)
{
_Fail("Compilation cancelled");
if (*cancelingPtr)
_Fail("Comptime evaluation canceled");
return false;
}
@ -4576,9 +4641,13 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (staticFieldInfo->mAddr == 0)
{
if (ceStaticFieldEntry.mSize < 0)
_Fail(StrFormat("Reference to unsized global variable '%s'", ceStaticFieldEntry.mName.c_str()));
CE_CHECKALLOC(ceStaticFieldEntry.mSize);
uint8* ptr = CeMalloc(ceStaticFieldEntry.mSize);
_FixVariables();
if (ceStaticFieldEntry.mSize > 0)
memset(ptr, 0, ceStaticFieldEntry.mSize);
staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
}
@ -4641,6 +4710,8 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction;
if (!callEntry.mFunction->mInitialized)
{
auto curFrame = _GetCurFrame();
SetAndRestoreValue<CeFrame*> prevFrame(mCurFrame, &curFrame);
PrepareFunction(callEntry.mFunction, NULL);
}
@ -4649,6 +4720,12 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
BF_ASSERT(memStart == mMemory.mVals);
auto callFunction = callEntry.mFunction;
if (callFunction->mMethodInstance->mMethodDef->mIsLocalMethod)
{
NOP;
}
if (needsFunctionIds)
*(int32*)(framePtr + resultFrameIdx) = callFunction->mId;
else
@ -4678,7 +4755,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CE_CHECKADDR(valueAddr, sizeof(int32));
int32 objTypeId = *(int32*)(memStart + valueAddr);
auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance();
BfType* bfType = GetBfType(objTypeId);
if ((bfType == NULL) || (!bfType->IsObject()))
{
_Fail("Invalid virtual method target");
return false;
}
auto valueType = bfType->ToTypeInstance();
if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod;
@ -4702,11 +4786,13 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CE_CHECKADDR(valueAddr, sizeof(int32));
int32 objTypeId = *(int32*)(memStart + valueAddr);
auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance();
BfMethodInstance* methodInstance = NULL;
if (valueType != NULL)
{
if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
BfMethodInstance* methodInstance = NULL;
auto checkType = valueType;
while (checkType != NULL)
{
@ -4720,6 +4806,7 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
}
checkType = checkType->mBaseType;
}
}
if (methodInstance == NULL)
{
@ -5305,18 +5392,25 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
auto owner = ceFunction->mMethodInstance->GetOwner();
if (owner == mCeModule->mContext->mBfObjectType)
{
if (methodDef->mName == "ConstEval_GetType")
if (methodDef->mName == "Comptime_GetType")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectType;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef))
{
if (methodDef->mName == "ConstEval_GetTypeById")
if (methodDef->mName == "Comptime_GetTypeById")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
{
if (methodDef->mName == "Comptime_EmitDefinition")
{
ceFunction->mFunctionKind = CeFunctionKind_EmitDefinition;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef))
{
if (methodDef->mName == "Write")
@ -5373,6 +5467,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
ceFunction->mGenerating = true;
CeBuilder ceBuilder;
SetAndRestoreValue<CeBuilder*> prevBuilder(mCurBuilder, &ceBuilder);
ceBuilder.mParentBuilder = parentBuilder;
ceBuilder.mPtrSize = mCeModule->mCompiler->mSystem->mPtrSize;
ceBuilder.mCeMachine = this;
@ -5534,6 +5629,7 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
// DISABLED
//return BfTypedValue();
SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags);
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);

View file

@ -251,6 +251,7 @@ enum CeFunctionKind
CeFunctionKind_DebugWrite_Int,
CeFunctionKind_GetReflectType,
CeFunctionKind_GetReflectTypeById,
CeFunctionKind_EmitDefinition,
CeFunctionKind_Sleep,
CeFunctionKind_Char32_ToLower,
CeFunctionKind_Char32_ToUpper,
@ -372,7 +373,9 @@ public:
enum CeEvalFlags
{
CeEvalFlags_None = 0,
CeEvalFlags_Cascade = 1
CeEvalFlags_Cascade = 1,
CeEvalFlags_PersistantError = 2,
CeEvalFlags_DeferIfNotOnlyError = 4,
};
enum CeOperandKind
@ -602,6 +605,18 @@ public:
BfIRValue mAppendSizeValue;
};
class CeEmitContext
{
public:
BfType* mType;
String mEmitData;
CeEmitContext()
{
mType = NULL;
}
};
class CeMachine
{
public:
@ -628,7 +643,11 @@ public:
HashSet<int> mStaticCtorExecSet;
CeAppendAllocInfo* mAppendAllocInfo;
CeEmitContext* mCurEmitContext;
CeEvalFlags mCurEvalFlags;
CeBuilder* mCurBuilder;
CeFunction* mPreparingFunction;
CeFrame* mCurFrame;
BfAstNode* mCurTargetSrc;
BfMethodInstance* mCurMethodInstance;
BfModule* mCurModule;
@ -650,6 +669,8 @@ public:
addr_ce GetConstantData(BeConstant* constant);
BfType* GetBfType(int typeId);
void PrepareConstStructEntry(CeConstStructData& constStructData);
bool CheckMemory(addr_ce addr, int32 size);
bool GetStringFromStringView(addr_ce addr, StringImpl& str);
BeContext* GetBeContext();
BeModule* GetBeModule();
@ -670,6 +691,7 @@ public:
public:
void CompileStarted();
void CompileDone();
void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
void QueueMethod(BfModuleMethodInstance moduleMethodInstance);
void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName);

View file

@ -23,8 +23,8 @@ namespace Tests
const String cStrA = "Abc";
const String cStrB = GetStringA(cStrA, 12, 23);
// ConstEval attribute means this method will always be const-evaluated
[ConstEval]
// Comptime attribute means this method will always be const-evaluated
[Comptime]
static String GetStringA(String str, int a, int b)
{
// Const-eval functions can return scope-allocated data
@ -101,7 +101,7 @@ namespace Tests
}
// This method can only be const evaluated
[ConstEval]
[Comptime]
public static int32 ConstSum(params int32[] vals)
{
int32 sum = 0;
@ -112,8 +112,8 @@ namespace Tests
public static int32 MethodB()
{
// Returns different results depending on whether we are const-evaluating
return Compiler.IsConstEval ? 1 : 0;
// Returns different results depending on whether we are comptime
return Compiler.IsComptime ? 1 : 0;
}
public static int32 MethodC(StructA sa = .(1, 2), (int32, int32) tup = (20, 30), int32[2] arr = .(300, 400))
@ -121,7 +121,7 @@ namespace Tests
return sa.mA + sa.mB + tup.0 + tup.1 + arr[0] + arr[1];
}
[ConstEval]
[Comptime(ConstEval=true)]
static var StrToValue(String str)
{
if (str.Contains('.'))
@ -164,7 +164,7 @@ namespace Tests
//Compiler.Assert(val1 == 24);
Test.Assert(val1 == 70);
// This method is marked as ConstEval so it always evaluates as const
// This method is marked as Comptime so it always evaluates as const
let val2 = ConstSum(3, 20, 100);
Compiler.Assert(val2 == 123);

View file

@ -195,6 +195,22 @@ namespace Tests
TI iface = val as TI;
}
public void MethodA<T>(List<T> list)
{
}
public void MethodA<T>(Span<T> list)
{
}
public void MethodB<T>()
{
List<T> list = null;
MethodA(list);
}
[Test]
public static void TestBasics()
{