1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +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,10 +274,36 @@ namespace System
} }
[AttributeUsage(.Method | .Invocation)] [AttributeUsage(.Method)]
public struct ComptimeAttribute : Attribute
{
public this()
{
}
public bool OnlyFromComptime
{
set
{
}
}
public bool ConstEval
{
set
{
}
}
}
[AttributeUsage(.Invocation)]
public struct ConstEvalAttribute : Attribute public struct ConstEvalAttribute : Attribute
{ {
public this()
{
}
} }
[AttributeUsage(.Method /*2*/)] [AttributeUsage(.Method /*2*/)]

View file

@ -1,7 +1,38 @@
using System.Reflection;
namespace System namespace System
{ {
[AttributeUsage(.Method)]
struct OnCompileAttribute : Attribute
{
public enum Kind
{
None,
TypeInit,
TypeDone
}
public this(Kind kind)
{
}
}
static class Compiler 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")] [LinkName("#CallerLineNum")]
public static extern int CallerLineNum; public static extern int CallerLineNum;
@ -32,8 +63,8 @@ namespace System
[LinkName("#TimeLocal")] [LinkName("#TimeLocal")]
public static extern String TimeLocal; public static extern String TimeLocal;
[LinkName("#IsConstEval")] [LinkName("#IsComptime")]
public static extern bool IsConstEval; public static extern bool IsComptime;
[LinkName("#IsBuilding")] [LinkName("#IsBuilding")]
public static extern bool IsBuilding; public static extern bool IsBuilding;
@ -44,11 +75,39 @@ namespace System
[LinkName("#CompileRev")] [LinkName("#CompileRev")]
public static extern int32 CompileRev; public static extern int32 CompileRev;
[ConstEval] [Comptime]
public static void Assert(bool cond) public static void Assert(bool cond)
{ {
if (!cond) if (!cond)
Runtime.FatalError("Assert failed"); 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 get
{ {
if (Compiler.IsConstEval) if (Compiler.IsComptime)
return InitUserDefaultCulture(); return InitUserDefaultCulture();
if (tlCurrentCulture == null) if (tlCurrentCulture == null)
tlCurrentCulture = CultureInfo.DefaultThreadCurrentCulture ?? CultureInfo.UserDefaultCulture; tlCurrentCulture = CultureInfo.DefaultThreadCurrentCulture ?? CultureInfo.UserDefaultCulture;

View file

@ -131,7 +131,7 @@ namespace System
public static T* AllocRawArrayUnmarked<T>(int size) public static T* AllocRawArrayUnmarked<T>(int size)
{ {
#if BF_ENABLE_REALTIME_LEAK_CHECK #if BF_ENABLE_REALTIME_LEAK_CHECK
if (Compiler.IsConstEval) if (Compiler.IsComptime)
return new T[size]*(?); return new T[size]*(?);
// We don't want to use the default mark function because the GC will mark the entire array, // 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 // 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. // _isCustomFormat, _specifierIsUpper, _specifier & _precision.
this(CultureInfo cultureInfo) this(CultureInfo cultureInfo)
{ {
if (Compiler.IsConstEval) if (Compiler.IsComptime)
_cbuf = new char8[0]; _cbuf = new char8[0];
else else
_cbuf = sEmtpyBuf; _cbuf = sEmtpyBuf;

View file

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

View file

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

View file

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

View file

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

View file

@ -61,6 +61,9 @@ namespace IDE.Compiler
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_Cancel(void* bfCompiler); static extern void BfCompiler_Cancel(void* bfCompiler);
[CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_RequestFastFinish(void* bfCompiler);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_ClearCompletionPercentage(void* bfCompiler); static extern void BfCompiler_ClearCompletionPercentage(void* bfCompiler);
@ -111,6 +114,12 @@ namespace IDE.Compiler
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_ForceRebuild(void* bfCompiler); 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 public enum HotTypeFlags
{ {
None = 0, None = 0,
@ -267,6 +276,20 @@ namespace IDE.Compiler
BfCompiler_ForceRebuild(mNativeBfCompiler); 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) public void QueueSetPassInstance(BfPassInstance passInstance)
{ {
SetPassInstanceCommand command = new SetPassInstanceCommand(); 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() public void ClearCompletionPercentage()
{ {
BfCompiler_ClearCompletionPercentage(mNativeBfCompiler); 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); return Utils.LoadTextFile(fileName, outBuffer, autoRetry, onPreFilter);
} }
@ -6145,6 +6162,16 @@ namespace IDE
useFilePath = scope:: String(useFilePath); 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))) if ((useFilePath != null) && (!IDEUtils.FixFilePath(useFilePath)))
return null; return null;
@ -6219,6 +6246,8 @@ namespace IDE
sourceViewPanelTab.mTabbedView.FinishTabAnim(); sourceViewPanelTab.mTabbedView.FinishTabAnim();
if (setFocus) if (setFocus)
sourceViewPanel.FocusEdit(); sourceViewPanel.FocusEdit();
sourceViewPanel.CheckEmitRevision();
} }
} }
@ -6236,6 +6265,7 @@ namespace IDE
} }
else else
success = sourceViewPanel.Show(useFilePath, !mInitialized); success = sourceViewPanel.Show(useFilePath, !mInitialized);
sourceViewPanel.mEmitRevision = emitRevision;
if (!success) 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 class SourceFindTask
{ {
public WaitEvent mDoneEvent = new WaitEvent() ~ delete _; public WaitEvent mDoneEvent = new WaitEvent() ~ delete _;
@ -306,6 +317,7 @@ namespace IDE.ui
public List<ResolveParams> mDeferredResolveResults = new .() ~ DeleteContainerAndItems!(_); public List<ResolveParams> mDeferredResolveResults = new .() ~ DeleteContainerAndItems!(_);
public bool mTrackedTextElementViewListDirty; public bool mTrackedTextElementViewListDirty;
public String mFilePath ~ delete _; public String mFilePath ~ delete _;
public int32 mEmitRevision = -1;
public bool mIsBinary; public bool mIsBinary;
public String mAliasFilePath ~ delete _; public String mAliasFilePath ~ delete _;
#if IDE_C_SUPPORT #if IDE_C_SUPPORT
@ -321,6 +333,7 @@ namespace IDE.ui
HTTPRequest mOldVerHTTPRequest ~ delete _; HTTPRequest mOldVerHTTPRequest ~ delete _;
IDEApp.ExecutionInstance mOldVerLoadExecutionInstance ~ { if (_ != null) _.mAutoDelete = true; }; IDEApp.ExecutionInstance mOldVerLoadExecutionInstance ~ { if (_ != null) _.mAutoDelete = true; };
SourceFindTask mSourceFindTask ~ delete _; SourceFindTask mSourceFindTask ~ delete _;
HoverResolveTask mHoverResolveTask ~ delete _;
bool mWantsFastClassify; bool mWantsFastClassify;
bool mWantsFullClassify; // This triggers a classify bool mWantsFullClassify; // This triggers a classify
bool mWantsFullRefresh; // If mWantsFullClassify is set, mWantsFullRefresh makes the whole thing refresh bool mWantsFullRefresh; // If mWantsFullClassify is set, mWantsFullRefresh makes the whole thing refresh
@ -579,6 +592,8 @@ namespace IDE.ui
if (ResolveCompiler.mThreadWorkerHi.mThreadRunning) if (ResolveCompiler.mThreadWorkerHi.mThreadRunning)
{ {
ResolveCompiler.RequestFastFinish();
//Debug.WriteLine("Deferred DoAutoComplete"); //Debug.WriteLine("Deferred DoAutoComplete");
DeleteAndNullify!(mQueuedAutoComplete); DeleteAndNullify!(mQueuedAutoComplete);
mQueuedAutoComplete = new .(); mQueuedAutoComplete = new .();
@ -968,6 +983,11 @@ namespace IDE.ui
//return; //return;
}*/ }*/
if (compiler.IsPerformingBackgroundOperation())
{
compiler.RequestFastFinish();
}
if (bfSystem == null) if (bfSystem == null)
return false; return false;
@ -1023,7 +1043,7 @@ namespace IDE.ui
bool doBackground = (useResolveType == ResolveType.Classify) || (useResolveType == ResolveType.ClassifyFullRefresh); bool doBackground = (useResolveType == ResolveType.Classify) || (useResolveType == ResolveType.ClassifyFullRefresh);
if (mAsyncAutocomplete) if (mAsyncAutocomplete)
{ {
if ((useResolveType == .Autocomplete) || (useResolveType == .GetCurrentLocation) || (useResolveType == .GetSymbolInfo)) if ((useResolveType == .Autocomplete) || (useResolveType == .GetCurrentLocation) || (useResolveType == .GetSymbolInfo) || (useResolveType == .GetResultString))
doBackground = true; doBackground = true;
} }
@ -1111,7 +1131,9 @@ namespace IDE.ui
bool isHi = (resolveType != .ClassifyFullRefresh) && (resolveType != .Classify); bool isHi = (resolveType != .ClassifyFullRefresh) && (resolveType != .Classify);
if (isHi) if (isHi)
{
Debug.Assert(!bfCompiler.mThreadWorkerHi.mThreadRunning); Debug.Assert(!bfCompiler.mThreadWorkerHi.mThreadRunning);
}
else else
Debug.Assert(!bfCompiler.mThreadWorker.mThreadRunning); Debug.Assert(!bfCompiler.mThreadWorker.mThreadRunning);
@ -1209,7 +1231,10 @@ namespace IDE.ui
var bfCompiler = BfResolveCompiler; var bfCompiler = BfResolveCompiler;
//var bfSystem = IDEApp.sApp.mBfResolveSystem; //var bfSystem = IDEApp.sApp.mBfResolveSystem;
//bfCompiler.StartTiming(); //bfCompiler.StartTiming();
DoClassify(ResolveType.Classify, resolveParams); ResolveType resolveType = ResolveType.Classify;
if (resolveParams != null)
resolveType = resolveParams.mResolveType;
DoClassify(resolveType, resolveParams);
//bfCompiler.StopTiming(); //bfCompiler.StopTiming();
if (bfCompiler != null) if (bfCompiler != null)
bfCompiler.QueueDeferredResolveAll(); bfCompiler.QueueDeferredResolveAll();
@ -1600,6 +1625,11 @@ namespace IDE.ui
} }
else if (resolveType == ResolveType.GetResultString) else if (resolveType == ResolveType.GetResultString)
{ {
if ((mHoverResolveTask != null) && (mHoverResolveTask.mCursorPos == resolveParams.mOverrideCursorPos))
{
mHoverResolveTask.mResult = new String(autocompleteInfo);
}
resolveParams.mResultString = new String(autocompleteInfo); resolveParams.mResultString = new String(autocompleteInfo);
} }
else if (resolveType == ResolveType.GetCurrentLocation) else if (resolveType == ResolveType.GetCurrentLocation)
@ -1664,7 +1694,7 @@ namespace IDE.ui
var bfCompiler = BfResolveCompiler; var bfCompiler = BfResolveCompiler;
//var compiler = ResolveCompiler; //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; bool fullRefresh = resolveType == ResolveType.ClassifyFullRefresh;
if (!isBackground) if (!isBackground)
@ -1775,15 +1805,18 @@ namespace IDE.ui
int cursorPos = mEditWidget.mEditWidgetContent.CursorTextPos; int cursorPos = mEditWidget.mEditWidgetContent.CursorTextPos;
/*if (resolveType == ResolveType.Autocomplete) /*if (resolveType == ResolveType.Autocomplete)
cursorPos--;*/ cursorPos--;*/
if ((resolveParams != null) && (resolveParams.mOverrideCursorPos != -1)) if (resolveParams != null)
cursorPos = resolveParams.mOverrideCursorPos; {
if (resolveParams.mOverrideCursorPos != -1)
cursorPos = resolveParams.mOverrideCursorPos;
}
if ((resolveType == ResolveType.GetNavigationData) || (resolveType == ResolveType.GetFixits)) if ((resolveType == ResolveType.GetNavigationData) || (resolveType == ResolveType.GetFixits))
parser.SetAutocomplete(-1); parser.SetAutocomplete(-1);
else else
{ {
bool setAutocomplete = ((!isBackground) && (resolveType != ResolveType.RenameSymbol)); bool setAutocomplete = ((!isBackground) && (resolveType != ResolveType.RenameSymbol));
if ((resolveType == .Autocomplete) || (resolveType == .GetCurrentLocation) || (resolveType == .GetSymbolInfo)) if ((resolveType == .Autocomplete) || (resolveType == .GetCurrentLocation) || (resolveType == .GetSymbolInfo) || (resolveType == .GetResultString))
setAutocomplete = true; setAutocomplete = true;
if (setAutocomplete) if (setAutocomplete)
parser.SetAutocomplete(Math.Max(0, cursorPos)); parser.SetAutocomplete(Math.Max(0, cursorPos));
@ -1866,7 +1899,9 @@ namespace IDE.ui
resolveParams.mCancelled = true; resolveParams.mCancelled = true;
if (resolveType == ResolveType.ClassifyFullRefresh) if (resolveType == ResolveType.ClassifyFullRefresh)
{
QueueFullRefresh(false); QueueFullRefresh(false);
}
bfCompiler.QueueDeferredResolveAll(); bfCompiler.QueueDeferredResolveAll();
} }
} }
@ -4639,6 +4674,7 @@ namespace IDE.ui
public void UpdateMouseover(bool mouseoverFired, bool mouseInbounds, int line, int lineChar) public void UpdateMouseover(bool mouseoverFired, bool mouseInbounds, int line, int lineChar)
{ {
#unwarn #unwarn
CompilerBase compiler = ResolveCompiler; 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 x;
float y; float y;
@ -4857,18 +4893,22 @@ namespace IDE.ui
String origDebugExpr = null; String origDebugExpr = null;
bool handlingHoverResolveTask = false;
if ((debugExpr != null) || (isOverMessage)) if ((debugExpr != null) || (isOverMessage))
{ {
let resolveParams = scope ResolveParams(); if (mHoverResolveTask != null)
resolveParams.mOverrideCursorPos = (int32)textIdx; {
if (!gApp.mDebugger.IsPaused()) if (mHoverResolveTask.mCursorPos != textIdx)
Classify(ResolveType.GetResultString, resolveParams); DeleteAndNullify!(mHoverResolveTask);
if (!String.IsNullOrEmpty(resolveParams.mResultString)) }
if ((!String.IsNullOrEmpty(mHoverResolveTask?.mResult)))
{ {
origDebugExpr = scope:: String(); origDebugExpr = scope:: String();
origDebugExpr.Set(debugExpr); origDebugExpr.Set(debugExpr);
debugExpr.Set(resolveParams.mResultString); debugExpr.Set(mHoverResolveTask.mResult);
if (debugExpr.StartsWith(':')) if (debugExpr.StartsWith(':'))
{ {
@ -4889,6 +4929,12 @@ namespace IDE.ui
} }
} }
if (mHoverResolveTask?.mResult != null)
{
handlingHoverResolveTask = true;
DeleteAndNullify!(mHoverResolveTask);
}
if (!triedShow) if (!triedShow)
{ {
mHoverWatch.Show(this, x, y, debugExpr, debugExpr); mHoverWatch.Show(this, x, y, debugExpr, debugExpr);
@ -4899,6 +4945,22 @@ namespace IDE.ui
if ((!didShow) && if ((!didShow) &&
((debugExpr == null) || (isOverMessage) || (!mHoverWatch.Show(this, x, y, origDebugExpr ?? debugExpr, debugExpr)))) ((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 IDE_C_SUPPORT
if ((mIsClang) && (textIdx != -1)) if ((mIsClang) && (textIdx != -1))
{ {
@ -4994,7 +5056,6 @@ namespace IDE.ui
{ {
mWantsFullRefresh = true; mWantsFullRefresh = true;
mRefireMouseOverAfterRefresh = true; mRefireMouseOverAfterRefresh = true;
//Debug.WriteLine("Full refresh...");
} }
} }
@ -5026,7 +5087,6 @@ namespace IDE.ui
{ {
if (mHoverWatch.mCloseDelay > 0) if (mHoverWatch.mCloseDelay > 0)
{ {
//Debug.WriteLine("mHoverWatch.mCloseCountdown = 20");
mHoverWatch.mCloseDelay--; mHoverWatch.mCloseDelay--;
mHoverWatch.mCloseCountdown = 20; mHoverWatch.mCloseCountdown = 20;
} }
@ -5042,7 +5102,6 @@ namespace IDE.ui
} }
else else
{ {
//Debug.WriteLine("mCloseCountdown = 0");
mHoverWatch.mCloseCountdown = 0; mHoverWatch.mCloseCountdown = 0;
} }
} }
@ -5088,7 +5147,7 @@ namespace IDE.ui
#if IDE_C_SUPPORT #if IDE_C_SUPPORT
hasClangHoverErrorData = mClangHoverErrorData != null; hasClangHoverErrorData = mClangHoverErrorData != null;
#endif #endif
if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData)) && if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData) || (mHoverResolveTask?.mResult != null)) &&
(mousePos.x >= 0)) (mousePos.x >= 0))
{ {
int line; 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) void DuplicateEditState(out EditWidgetContent.CharData[] char8Data, out IdSpan char8IdData)
{ {
var srcCharData = mEditWidget.Content.mData.mText; var srcCharData = mEditWidget.Content.mData.mText;
@ -5840,6 +5450,13 @@ namespace IDE.ui
checkIdx++; checkIdx++;
continue; continue;
} }
if (!resolveResult.mWaitEvent.WaitFor(0))
{
if (waitTime != 0)
ResolveCompiler.RequestFastFinish();
}
if (!resolveResult.mWaitEvent.WaitFor(waitTime)) if (!resolveResult.mWaitEvent.WaitFor(waitTime))
{ {
checkIdx++; checkIdx++;
@ -5847,6 +5464,9 @@ namespace IDE.ui
} }
mDeferredResolveResults.RemoveAt(checkIdx); mDeferredResolveResults.RemoveAt(checkIdx);
} }
//Debug.WriteLine($"HandleResolveResult {resolveResult}");
HandleResolveResult(resolveResult.mResolveType, resolveResult.mAutocompleteInfo, resolveResult); HandleResolveResult(resolveResult.mResolveType, resolveResult.mAutocompleteInfo, resolveResult);
//Debug.WriteLine("ProcessDeferredResolveResults finished {0}", resolveResult.mResolveType); //Debug.WriteLine("ProcessDeferredResolveResults finished {0}", resolveResult.mResolveType);
@ -5887,12 +5507,15 @@ namespace IDE.ui
{ {
MarkDirty(); MarkDirty();
if (resolveResult.mPassInstance.HadSignatureChanges()) if (resolveResult.mPassInstance.HadSignatureChanges())
{
mWantsFullRefresh = true; mWantsFullRefresh = true;
}
} }
} }
/*if (checkIt) /*if (checkIt)
Debug.Assert(data.mDisplayTypeId == 8);*/ Debug.Assert(data.mDisplayTypeId == 8);*/
//Debug.WriteLine($"Deleting {resolveResult}");
delete resolveResult; delete resolveResult;
} }
} }
@ -6368,6 +5991,9 @@ namespace IDE.ui
mLockFlashPct = 0; mLockFlashPct = 0;
MarkDirty(); MarkDirty();
} }
if ((mEmitRevision >= 0) && ((mUpdateCnt % 30) == 0))
CheckEmitRevision();
} }
void InjectErrors(BfPassInstance processingPassInstance, EditWidgetContent.CharData[] processResolveCharData, IdSpan processCharIdSpan, bool keepPersistentErrors) void InjectErrors(BfPassInstance processingPassInstance, EditWidgetContent.CharData[] processResolveCharData, IdSpan processCharIdSpan, bool keepPersistentErrors)
@ -6396,10 +6022,14 @@ namespace IDE.ui
int32 errorCount = processingPassInstance.GetErrorCount(); int32 errorCount = processingPassInstance.GetErrorCount();
mErrorList.Capacity = mErrorList.Count + errorCount; mErrorList.Capacity = mErrorList.Count + errorCount;
bool hadNonDeferredErrors = false;
for (int32 errorIdx = 0; errorIdx < errorCount; errorIdx++) for (int32 errorIdx = 0; errorIdx < errorCount; errorIdx++)
{ {
BfPassInstance.BfError bfError = new BfPassInstance.BfError(); BfPassInstance.BfError bfError = new BfPassInstance.BfError();
processingPassInstance.GetErrorData(errorIdx, bfError); processingPassInstance.GetErrorData(errorIdx, bfError);
if (!bfError.mIsDeferred)
hadNonDeferredErrors = true;
for (int32 moreInfoIdx < bfError.mMoreInfoCount) for (int32 moreInfoIdx < bfError.mMoreInfoCount)
{ {
@ -6425,6 +6055,9 @@ namespace IDE.ui
if (bfError.mIsWhileSpecializing) if (bfError.mIsWhileSpecializing)
continue; continue;
if ((bfError.mIsDeferred) && (hadNonDeferredErrors))
continue;
if (bfError.mIsPersistent) if (bfError.mIsPersistent)
{ {
if (bfError.mIdSpan.IsEmpty) if (bfError.mIdSpan.IsEmpty)
@ -6823,5 +6456,27 @@ namespace IDE.ui
return false; 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); beValue = mBeModule->CreateUndefValue(type);
return; 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; bool isSigned = false;
BeType* llvmConstType = GetBeType(typeCode, isSigned); BeType* llvmConstType = GetBeType(typeCode, isSigned);
@ -1969,6 +1984,13 @@ void BeIRCodeGen::HandleNextCmd()
//SetResult(curId, globalVariable); //SetResult(curId, globalVariable);
} }
break; break;
case BfIRCmd_SetReflectTypeData:
{
CMD_PARAM(BeType*, type);
CMD_PARAM(BeValue*, value);
mReflectDataMap[type] = value;
}
break;
case BfIRCmd_CreateBlock: case BfIRCmd_CreateBlock:
{ {
CMD_PARAM(String, name); CMD_PARAM(String, name);

View file

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

View file

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

View file

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

View file

@ -346,6 +346,8 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
memset(&mStats, 0, sizeof(mStats)); memset(&mStats, 0, sizeof(mStats));
mCompletionPct = 0; mCompletionPct = 0;
mCanceling = false; mCanceling = false;
mFastFinish = false;
mHasQueuedTypeRebuilds = false;
mIsResolveOnly = isResolveOnly; mIsResolveOnly = isResolveOnly;
mResolvePassData = NULL; mResolvePassData = NULL;
mPassInstance = NULL; mPassInstance = NULL;
@ -397,6 +399,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mActionTypeDef = NULL; mActionTypeDef = NULL;
mEnumTypeDef = NULL; mEnumTypeDef = NULL;
mFriendAttributeTypeDef = NULL; mFriendAttributeTypeDef = NULL;
mComptimeAttributeTypeDef = NULL;
mConstEvalAttributeTypeDef = NULL; mConstEvalAttributeTypeDef = NULL;
mNoExtensionAttributeTypeDef = NULL; mNoExtensionAttributeTypeDef = NULL;
mCheckedAttributeTypeDef = NULL; mCheckedAttributeTypeDef = NULL;
@ -408,11 +411,14 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mGenericIRefEnumeratorTypeDef = NULL; mGenericIRefEnumeratorTypeDef = NULL;
mInlineAttributeTypeDef = NULL; mInlineAttributeTypeDef = NULL;
mThreadTypeDef = NULL; mThreadTypeDef = NULL;
mInternalTypeDef = NULL; mInternalTypeDef = NULL;
mCompilerTypeDef = NULL;
mDiagnosticsDebugTypeDef = NULL; mDiagnosticsDebugTypeDef = NULL;
mIDisposableTypeDef = NULL; mIDisposableTypeDef = NULL;
mIPrintableTypeDef = NULL; mIPrintableTypeDef = NULL;
mIHashableTypeDef = NULL; mIHashableTypeDef = NULL;
mIComptimeTypeApply = NULL;
mIComptimeMethodApply = NULL;
mLinkNameAttributeTypeDef = NULL; mLinkNameAttributeTypeDef = NULL;
mCallingConventionAttributeTypeDef = NULL; mCallingConventionAttributeTypeDef = NULL;
mMethodRefTypeDef = NULL; mMethodRefTypeDef = NULL;
@ -447,6 +453,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mWarnAttributeTypeDef = NULL; mWarnAttributeTypeDef = NULL;
mIgnoreErrorsAttributeTypeDef = NULL; mIgnoreErrorsAttributeTypeDef = NULL;
mReflectAttributeTypeDef = NULL; mReflectAttributeTypeDef = NULL;
mOnCompileAttributeTypeDef = NULL;
mLastAutocompleteModule = NULL; mLastAutocompleteModule = NULL;
@ -3919,6 +3926,8 @@ void BfCompiler::ProcessAutocompleteTempType()
return; return;
} }
mFastFinish = false;
SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, NULL); SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, NULL);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, NULL); SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, NULL);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, NULL); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, NULL);
@ -6522,13 +6531,15 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
if (IsHotCompile()) if (IsHotCompile())
{ {
mContext->EnsureHotMangledVirtualMethodNames(); mContext->EnsureHotMangledVirtualMethodNames();
} }
mOutputDirectory = outputDirectory; mOutputDirectory = outputDirectory;
mSystem->StartYieldSection(); mSystem->StartYieldSection();
mFastFinish = false;
mHasQueuedTypeRebuilds = false;
mCanceling = false; mCanceling = false;
mSystem->CheckLockYield(); mSystem->CheckLockYield();
@ -6611,6 +6622,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mActionTypeDef = _GetRequiredType("System.Action"); mActionTypeDef = _GetRequiredType("System.Action");
mEnumTypeDef = _GetRequiredType("System.Enum"); mEnumTypeDef = _GetRequiredType("System.Enum");
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute"); mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute");
mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute"); mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute");
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute"); mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");
mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute"); mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute");
@ -6624,10 +6636,13 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute"); mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
mThreadTypeDef = _GetRequiredType("System.Threading.Thread"); mThreadTypeDef = _GetRequiredType("System.Threading.Thread");
mInternalTypeDef = _GetRequiredType("System.Internal"); mInternalTypeDef = _GetRequiredType("System.Internal");
mCompilerTypeDef = _GetRequiredType("System.Compiler");
mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug"); mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
mIDisposableTypeDef = _GetRequiredType("System.IDisposable"); mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
mIPrintableTypeDef = _GetRequiredType("System.IPrintable"); mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
mIHashableTypeDef = _GetRequiredType("System.IHashable"); mIHashableTypeDef = _GetRequiredType("System.IHashable");
mIComptimeTypeApply = _GetRequiredType("System.IComptimeTypeApply");
mIComptimeMethodApply = _GetRequiredType("System.IComptimeMethodApply");
mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute"); mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute");
mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute"); mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute");
mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1); mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1);
@ -6662,6 +6677,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute"); mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute"); mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute");
mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute"); mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute");
mOnCompileAttributeTypeDef = _GetRequiredType("System.OnCompileAttribute");
for (int i = 0; i < BfTypeCode_Length; i++) for (int i = 0; i < BfTypeCode_Length; i++)
mContext->mPrimitiveStructTypes[i] = NULL; mContext->mPrimitiveStructTypes[i] = NULL;
@ -7213,6 +7229,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
} }
mCodeGen.ProcessErrors(mPassInstance, mCanceling); mCodeGen.ProcessErrors(mPassInstance, mCanceling);
mCEMachine->CompileDone();
// This has to happen after codegen because we may delete modules that are referenced in codegen // This has to happen after codegen because we may delete modules that are referenced in codegen
mContext->Cleanup(); mContext->Cleanup();
if ((!IsHotCompile()) && (!mIsResolveOnly) && (!mCanceling)) if ((!IsHotCompile()) && (!mIsResolveOnly) && (!mCanceling))
@ -7346,7 +7364,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mContext->ValidateDependencies(); mContext->ValidateDependencies();
return !didCancel; return !didCancel && !mHasQueuedTypeRebuilds;
} }
bool BfCompiler::Compile(const StringImpl& outputDirectory) bool BfCompiler::Compile(const StringImpl& outputDirectory)
@ -7380,11 +7398,19 @@ void BfCompiler::ClearResults()
void BfCompiler::Cancel() void BfCompiler::Cancel()
{ {
mCanceling = true; mCanceling = true;
mFastFinish = true;
mHadCancel = true; mHadCancel = true;
BfLogSysM("BfCompiler::Cancel\n"); BfLogSysM("BfCompiler::Cancel\n");
BpEvent("BfCompiler::Cancel", ""); BpEvent("BfCompiler::Cancel", "");
} }
void BfCompiler::RequestFastFinish()
{
mFastFinish = true;
BfLogSysM("BfCompiler::RequestFastFinish\n");
BpEvent("BfCompiler::RequestFastFinish", "");
}
//#define WANT_COMPILE_LOG //#define WANT_COMPILE_LOG
void BfCompiler::CompileLog(const char* fmt ...) void BfCompiler::CompileLog(const char* fmt ...)
@ -8538,6 +8564,38 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
return result; 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); PerfManager* BfGetPerfManager(BfParser* bfParser);
@ -8738,6 +8796,11 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_Cancel(BfCompiler* bfCompiler)
bfCompiler->Cancel(); bfCompiler->Cancel();
} }
BF_EXPORT void BF_CALLTYPE BfCompiler_RequestFastFinish(BfCompiler* bfCompiler)
{
bfCompiler->RequestFastFinish();
}
BF_EXPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(BfCompiler* bfCompiler) BF_EXPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(BfCompiler* bfCompiler)
{ {
bfCompiler->ClearBuildCache(); bfCompiler->ClearBuildCache();
@ -9251,3 +9314,17 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler)
bfCompiler->mOptions.mForceRebuildIdx++; 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; BfCodeGen mCodeGen;
String mOutputDirectory; String mOutputDirectory;
bool mCanceling; bool mCanceling;
bool mFastFinish;
bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild
bool mHadCancel; bool mHadCancel;
bool mWantsDeferMethodDecls; bool mWantsDeferMethodDecls;
bool mInInvalidState; bool mInInvalidState;
@ -362,10 +364,13 @@ public:
BfTypeDef* mThreadTypeDef; BfTypeDef* mThreadTypeDef;
BfTypeDef* mInternalTypeDef; BfTypeDef* mInternalTypeDef;
BfTypeDef* mCompilerTypeDef;
BfTypeDef* mDiagnosticsDebugTypeDef; BfTypeDef* mDiagnosticsDebugTypeDef;
BfTypeDef* mIDisposableTypeDef; BfTypeDef* mIDisposableTypeDef;
BfTypeDef* mIPrintableTypeDef; BfTypeDef* mIPrintableTypeDef;
BfTypeDef* mIHashableTypeDef; BfTypeDef* mIHashableTypeDef;
BfTypeDef* mIComptimeTypeApply;
BfTypeDef* mIComptimeMethodApply;
BfTypeDef* mMethodRefTypeDef; BfTypeDef* mMethodRefTypeDef;
BfTypeDef* mNullableTypeDef; BfTypeDef* mNullableTypeDef;
@ -403,6 +408,7 @@ public:
BfTypeDef* mDisableChecksAttributeTypeDef; BfTypeDef* mDisableChecksAttributeTypeDef;
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef; BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
BfTypeDef* mFriendAttributeTypeDef; BfTypeDef* mFriendAttributeTypeDef;
BfTypeDef* mComptimeAttributeTypeDef;
BfTypeDef* mConstEvalAttributeTypeDef; BfTypeDef* mConstEvalAttributeTypeDef;
BfTypeDef* mNoExtensionAttributeTypeDef; BfTypeDef* mNoExtensionAttributeTypeDef;
BfTypeDef* mCheckedAttributeTypeDef; BfTypeDef* mCheckedAttributeTypeDef;
@ -417,6 +423,7 @@ public:
BfTypeDef* mWarnAttributeTypeDef; BfTypeDef* mWarnAttributeTypeDef;
BfTypeDef* mIgnoreErrorsAttributeTypeDef; BfTypeDef* mIgnoreErrorsAttributeTypeDef;
BfTypeDef* mReflectAttributeTypeDef; BfTypeDef* mReflectAttributeTypeDef;
BfTypeDef* mOnCompileAttributeTypeDef;
int mCurTypeId; int mCurTypeId;
int mTypeInitCount; int mTypeInitCount;
@ -493,9 +500,11 @@ public:
void ProcessAutocompleteTempType(); void ProcessAutocompleteTempType();
void GetSymbolReferences(); void GetSymbolReferences();
void Cancel(); void Cancel();
void RequestFastFinish();
String GetTypeDefList(); String GetTypeDefList();
String GetTypeDefMatches(const StringImpl& searchSrc); String GetTypeDefMatches(const StringImpl& searchSrc);
String GetTypeDefInfo(const StringImpl& typeName); String GetTypeDefInfo(const StringImpl& typeName);
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
void CompileLog(const char* fmt ...); void CompileLog(const char* fmt ...);
void ReportMemory(MemReporter* memReporter); 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) 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 // Handle the 'int[?] val = .(1, 2, 3)' case
if ((flags & BfConstResolveFlag_ArrayInitSize) != 0) 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) || if ((typeDef->mDefState == BfTypeDef::DefState_New) ||
(typeDef->mDefState == BfTypeDef::DefState_Deleted) || (typeDef->mDefState == BfTypeDef::DefState_Deleted) ||
@ -1025,6 +1025,11 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
typeInst->mHasDeclError = false; typeInst->mHasDeclError = false;
delete typeInst->mTypeInfoEx; delete typeInst->mTypeInfoEx;
typeInst->mTypeInfoEx = NULL; typeInst->mTypeInfoEx = NULL;
typeInst->mTypeDef->ClearEmitted();
for (auto localMethod : typeInst->mOwnedLocalMethods)
delete localMethod;
typeInst->mOwnedLocalMethods.Clear();
if (typeInst->IsGenericTypeInstance()) if (typeInst->IsGenericTypeInstance())
{ {
@ -2851,7 +2856,24 @@ void BfContext::Cleanup()
for (auto localMethod : mLocalMethodGraveyard) 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(); localMethod->Dispose();
survivingLocalMethods.push_back(localMethod); survivingLocalMethods.push_back(localMethod);

View file

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

View file

@ -799,7 +799,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
SET_BETTER_OR_WORSE((!isUnspecializedParam) && (!paramType->IsVar()), SET_BETTER_OR_WORSE((!isUnspecializedParam) && (!paramType->IsVar()),
(!isPrevUnspecializedParam) && (!prevParamType->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()), SET_BETTER_OR_WORSE((paramType != NULL) && (!paramType->IsUnspecializedType()),
(prevParamType != NULL) && (!prevParamType->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)) if ((origParamType != origPrevParamType) && (paramWasConstExpr) && (!prevParamWasConstExpr))
betterByConstExprParam = true; betterByConstExprParam = true;
@ -2698,21 +2699,21 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete()
return mModule->mCompiler->mResolvePassData->mAutoComplete; 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 false;
return ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0); return ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0);
} }
int BfExprEvaluator::GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic) int BfExprEvaluator::GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic)
{ {
if (IsConstEval()) if (IsComptime())
return -1; return -1;
return methodInstance->GetStructRetIdx(forceStatic); return methodInstance->GetStructRetIdx(forceStatic);
} }
@ -3333,7 +3334,7 @@ void BfExprEvaluator::Visit(BfLiteralExpression* literalExpr)
void BfExprEvaluator::Visit(BfStringInterpolationExpression* stringInterpolationExpression) void BfExprEvaluator::Visit(BfStringInterpolationExpression* stringInterpolationExpression)
{ {
if (IsConstEvalEntry()) if (IsComptimeEntry())
{ {
mModule->Fail("Const evaluation of string interpolation not allowed", stringInterpolationExpression); mModule->Fail("Const evaluation of string interpolation not allowed", stringInterpolationExpression);
} }
@ -5075,43 +5076,57 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if ((mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCompiler->mResolvePassData->mAutoComplete != NULL)) if ((mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCompiler->mResolvePassData->mAutoComplete != NULL))
{ {
// In an autocomplete pass we may have stale method references that need to be resolved bool wantQuickEval = true;
// in the full classify pass, and in the full classify pass while just refreshing internals, we
// may have NULL funcs temporarily. We simply skip generating the method call here. if (IsComptime())
if (methodInstance->mVirtualTableIdx == -1) {
{ auto autoComplete = mModule->mCompiler->mResolvePassData->mAutoComplete;
if (methodInstance->GetOwner()->IsInterface()) wantQuickEval =
{ ((autoComplete->mResolveType != BfResolveType_Autocomplete) &&
// We're attempting to directly invoke a non-virtual interface method, if we're return an interface then (autoComplete->mResolveType != BfResolveType_Autocomplete_HighPri) &&
// it is a concrete interface (autoComplete->mResolveType != BfResolveType_GetResultString));
if (returnType->IsInterface())
returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance());
}
} }
if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) if (wantQuickEval)
{ {
if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) // 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
// may have NULL funcs temporarily. We simply skip generating the method call here.
if (methodInstance->mVirtualTableIdx == -1)
{ {
if ((mExpectingType != NULL) && (mExpectingType->IsSizedArray())) if (methodInstance->GetOwner()->IsInterface())
{ {
return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(mExpectingType)), mExpectingType); // We're attempting to directly invoke a non-virtual interface method, if we're return an interface then
// it is a concrete interface
if (returnType->IsInterface())
returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance());
} }
} }
auto returnType = methodInstance->mReturnType;
if ((returnType->IsVar()) && (mExpectingType != NULL))
returnType = mExpectingType;
if (methodInstance->mReturnType->IsValuelessType())
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), returnType);
return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(returnType)), returnType);
}
BfTypedValue result; if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
if (sret != NULL) {
result = *sret; if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
else {
result = _GetDefaultReturnValue(); if ((mExpectingType != NULL) && (mExpectingType->IsSizedArray()))
return result; {
return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(mExpectingType)), mExpectingType);
}
}
auto returnType = methodInstance->mReturnType;
if ((returnType->IsVar()) && (mExpectingType != NULL))
returnType = mExpectingType;
if (methodInstance->mReturnType->IsValuelessType())
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), returnType);
return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(returnType)), returnType);
}
BfTypedValue result;
if (sret != NULL)
result = *sret;
else
result = _GetDefaultReturnValue();
return result;
}
} }
bool forceBind = false; bool forceBind = false;
@ -5120,7 +5135,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{ {
bool doConstReturn = false; bool doConstReturn = false;
if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
{ {
if (mFunctionBindResult != NULL) if (mFunctionBindResult != NULL)
{ {
@ -5134,6 +5149,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{ {
doConstReturn = true; 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 else
{ {
CeEvalFlags evalFlags = CeEvalFlags_None; CeEvalFlags evalFlags = CeEvalFlags_None;
@ -5143,9 +5163,20 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
BF_ASSERT(!constRet.mType->IsVar()); BF_ASSERT(!constRet.mType->IsVar());
return constRet; 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) if (methodInstance->mIsUnspecialized)
{ {
@ -5206,7 +5237,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface()) 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); 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); funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr);
} }
} }
else if (mModule->mIsConstModule) else if (mModule->mIsComptimeModule)
{ {
funcCallInst = mModule->mBfIRBuilder->ConstEval_GetVirtualFunc(irArgs[0], methodInstance->mVirtualTableIdx, funcPtrType1); funcCallInst = mModule->mBfIRBuilder->ConstEval_GetVirtualFunc(irArgs[0], methodInstance->mVirtualTableIdx, funcPtrType1);
} }
@ -5323,7 +5354,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (irArgs.size() != 0) if (irArgs.size() != 0)
{ {
auto targetType = methodInstance->mMethodInstanceGroup->mOwner; 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); mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, BfTypedValueKind_SplatHead);
else else
mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, targetType->IsComposite() ? BfTypedValueKind_Addr : BfTypedValueKind_Value); 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); mModule->PopulateType(paramType, BfPopulateType_Data);
auto typeInst = paramType->ToTypeInstance(); auto typeInst = paramType->ToTypeInstance();
if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsConstEval())) if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsComptime()))
{ {
// We're splatting // We're splatting
} }
@ -5527,7 +5558,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
doingThis = false; doingThis = false;
continue; continue;
} }
bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsConstEval()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating); bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsComptime()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
if (isSplatted) if (isSplatted)
{ {
BfTypeUtils::SplatIterate(_HandleParamType, paramType); BfTypeUtils::SplatIterate(_HandleParamType, paramType);
@ -5561,7 +5592,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
continue; continue;
} }
if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsConstEval())) if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsComptime()))
{ {
BfTypeUtils::SplatIterate(_HandleParamType, paramType); BfTypeUtils::SplatIterate(_HandleParamType, paramType);
paramIdx++; paramIdx++;
@ -5614,7 +5645,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
{ {
BfTypeCode loweredRetType = BfTypeCode_None; BfTypeCode loweredRetType = BfTypeCode_None;
BfTypeCode loweredRetType2 = BfTypeCode_None; BfTypeCode loweredRetType2 = BfTypeCode_None;
if ((!IsConstEval()) && (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2))) if ((!IsComptime()) && (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2)))
{ {
auto retVal = mModule->CreateAlloca(methodInstance->mReturnType); auto retVal = mModule->CreateAlloca(methodInstance->mReturnType);
BfIRType loweredIRType = mModule->GetIRLoweredType(loweredRetType, loweredRetType2); BfIRType loweredIRType = mModule->GetIRLoweredType(loweredRetType, loweredRetType2);
@ -5780,7 +5811,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
return; return;
bool wantSplat = false; bool wantSplat = false;
if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsConstEval())) if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime()))
{ {
disableLowering = true; disableLowering = true;
auto argTypeInstance = argVal.mType->ToTypeInstance(); auto argTypeInstance = argVal.mType->ToTypeInstance();
@ -5801,7 +5832,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
{ {
if (argVal.mType->IsComposite()) 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 // Const eval entry - we want any incoming consts as they are
} }
@ -5812,7 +5843,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
else else
argVal = mModule->MakeAddressable(argVal); argVal = mModule->MakeAddressable(argVal);
if ((!IsConstEval()) && (!disableLowering) && (!isIntrinsic)) if ((!IsComptime()) && (!disableLowering) && (!isIntrinsic))
{ {
BfTypeCode loweredTypeCode = BfTypeCode_None; BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None; BfTypeCode loweredTypeCode2 = BfTypeCode_None;
@ -5906,7 +5937,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
auto owner = methodInstance->GetOwner(); auto owner = methodInstance->GetOwner();
bool allowThisSplatting; bool allowThisSplatting;
if (mModule->mIsConstModule) if (mModule->mIsComptimeModule)
allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType(); allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType();
else else
allowThisSplatting = methodInstance->AllowsSplatting(-1); allowThisSplatting = methodInstance->AllowsSplatting(-1);
@ -6210,7 +6241,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
} }
else else
{ {
wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsConstEval()); wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsComptime());
if (methodInstance->IsImplicitCapture(paramIdx)) if (methodInstance->IsImplicitCapture(paramIdx))
{ {
auto paramType = methodInstance->GetParamType(paramIdx); auto paramType = methodInstance->GetParamType(paramIdx);
@ -6275,7 +6306,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (methodDef->mMethodType == BfMethodType_Extension) if (methodDef->mMethodType == BfMethodType_Extension)
numElements++; numElements++;
if (IsConstEvalEntry()) if (IsComptimeEntry())
{ {
if ((wantType->IsArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) if ((wantType->IsArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
{ {
@ -6694,7 +6725,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
else else
{ {
// We need to make a temp and get the addr of that // 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); argValue = mModule->MakeAddressable(argValue);
} }
@ -6714,7 +6745,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
{ {
if (argValue) if (argValue)
{ {
if (IsConstEvalEntry()) if (IsComptimeEntry())
{ {
auto constant = mModule->mBfIRBuilder->GetConstant(expandedParamsArray.mValue); auto constant = mModule->mBfIRBuilder->GetConstant(expandedParamsArray.mValue);
BF_ASSERT(constant->mConstType == BfConstType_Agg); BF_ASSERT(constant->mConstType == BfConstType_Agg);
@ -8588,15 +8619,28 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
// //
{ {
SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags); SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags);
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef))) if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
{ {
mModule->mAttributeState->mUsed = true; 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); 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++) for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
{ {
auto paramType = methodInstance->GetParamType(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); 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? // Actually leave it alone?
if ((isUninit) && if ((isUninit) &&
((mModule->IsOptimized()) || (mModule->mIsConstModule) || (mModule->mBfIRBuilder->mIgnoreWrites))) ((mModule->IsOptimized()) || (mModule->mIsComptimeModule) || (mModule->mBfIRBuilder->mIgnoreWrites)))
return; return;
bool doClear = true; bool doClear = true;
@ -13564,7 +13608,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{ {
allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign); 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); mModule->mCompiler->mCEMachine->SetAppendAllocInfo(mModule, allocValue, appendSizeValue);
} }
@ -13615,7 +13659,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{ {
mModule->AssertErrorState(); mModule->AssertErrorState();
} }
else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) == 0) else if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) == 0)
{ {
SizedArray<BfIRValue, 1> irArgs; SizedArray<BfIRValue, 1> irArgs;
irArgs.push_back(mResult.mValue); 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"); BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers");
BF_ASSERT(markMethod != NULL); 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(); mModule->mCompiler->mCEMachine->ClearAppendAllocInfo();
} }
@ -13887,7 +13931,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
if ((target.mType->IsStruct()) && (!target.IsAddr())) if ((target.mType->IsStruct()) && (!target.IsAddr()))
{ {
if (IsConstEvalEntry()) if (IsComptimeEntry())
return target; return target;
target = mModule->MakeAddressable(target); target = mModule->MakeAddressable(target);
} }
@ -13923,7 +13967,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
auto ptrType = mModule->CreatePointerType(primStructType); auto ptrType = mModule->CreatePointerType(primStructType);
target = BfTypedValue(mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->MapType(ptrType)), primStructType, true); 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.mType = primStructType;
target.mKind = BfTypedValueKind_SplatHead; target.mKind = BfTypedValueKind_SplatHead;
@ -15739,7 +15783,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
int methodCount = 0; int methodCount = 0;
bool mayBeSkipCall = false; bool mayBeSkipCall = false;
bool mayBeConstEvalCall = false; bool mayBeComptimeCall = false;
if (thisValue.mType != NULL) if (thisValue.mType != NULL)
{ {
if (thisValue.mType->IsAllocType()) if (thisValue.mType->IsAllocType())
@ -15757,8 +15801,8 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
{ {
if (methodDef->mIsSkipCall) if (methodDef->mIsSkipCall)
mayBeSkipCall = true; mayBeSkipCall = true;
if (methodDef->mIsConstEval) if (methodDef->mHasComptime)
mayBeConstEvalCall = true; mayBeComptimeCall = true;
methodDef = methodDef->mNextWithSameName; methodDef = methodDef->mNextWithSameName;
} }
} }
@ -15784,7 +15828,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
BfResolveArgsFlags resolveArgsFlags = (BfResolveArgsFlags)(BfResolveArgsFlag_DeferFixits | BfResolveArgsFlag_AllowUnresolvedTypes); BfResolveArgsFlags resolveArgsFlags = (BfResolveArgsFlags)(BfResolveArgsFlag_DeferFixits | BfResolveArgsFlag_AllowUnresolvedTypes);
resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamEval); resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamEval);
if ((mayBeSkipCall) || (mayBeConstEvalCall)) if ((mayBeSkipCall) || (mayBeComptimeCall))
resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamValues); resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamValues);
static int sCallIdx = 0; 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); mModule->Fail("Cascade operator cannot be used in const evaluation", cascadeOperatorToken);
SetAndRestoreValue<bool> prevUsedAsStatement(mUsedAsStatement, mUsedAsStatement || isCascade); SetAndRestoreValue<bool> prevUsedAsStatement(mUsedAsStatement, mUsedAsStatement || isCascade);
@ -16061,7 +16105,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
} }
} }
} }
if ((mOrigPropTarget) && (mOrigPropTarget.mType != mPropTarget.mType) && if ((mOrigPropTarget) && (mOrigPropTarget.mType != mPropTarget.mType) &&
((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface()))) ((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface())))
{ {
@ -16080,6 +16124,10 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
while (checkTypeInst != NULL) while (checkTypeInst != NULL)
{ {
mModule->PopulateType(checkTypeInst, BfPopulateType_DataAndMethods); 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) for (auto& iface : checkTypeInst->mInterfaces)
{ {
@ -16132,7 +16180,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
} }
if (bestIFaceEntry != NULL) if (bestIFaceEntry != NULL)
{ {
auto ifaceMethodEntry = checkTypeInst->mInterfaceMethodTable[bestIFaceEntry->mStartInterfaceTableIdx + methodDef->mIdx]; auto ifaceMethodEntry = checkTypeInst->mInterfaceMethodTable[bestIFaceEntry->mStartInterfaceTableIdx + methodDef->mIdx];
BfMethodInstance* bestMethodInstance = ifaceMethodEntry.mMethodRef; BfMethodInstance* bestMethodInstance = ifaceMethodEntry.mMethodRef;
if (bestMethodInstance != NULL) if (bestMethodInstance != NULL)
@ -18735,7 +18783,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
} }
} }
} }
else if (((mModule->HasCompiledOutput()) || (mModule->mIsConstModule)) && else if (((mModule->HasCompiledOutput()) || (mModule->mIsComptimeModule)) &&
(wantsChecks)) (wantsChecks))
{ {
if (checkedKind == BfCheckedKind_NotSet) if (checkedKind == BfCheckedKind_NotSet)
@ -18767,7 +18815,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
OutputDebugStrF("-OOB %d %d\n", oobFunc.mFunc.mId, oobFunc.mFunc.mFlags); 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); mModule->mCompiler->mCEMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc);
SizedArray<BfIRValue, 1> args; SizedArray<BfIRValue, 1> args;

View file

@ -390,8 +390,8 @@ public:
void FinishExpressionResult(); void FinishExpressionResult();
virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode); virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode);
BfAutoComplete* GetAutoComplete(); BfAutoComplete* GetAutoComplete();
bool IsConstEval(); bool IsComptime();
bool IsConstEvalEntry(); bool IsComptimeEntry();
int GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic = false); int GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic = false);
BfTypedValue SetupNullConditional(BfTypedValue target, BfTokenNode* dotToken); BfTypedValue SetupNullConditional(BfTypedValue target, BfTokenNode* dotToken);
void Evaluate(BfAstNode* astNode, bool propogateNullConditional = false, bool ignoreNullConditional = false, bool allowSplat = true); 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; auto typeOf = (BfTypeOf_Const*)fromConst;
return CreateTypeOf(typeOf->mType); 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) else if (fromConst->mConstType == BfConstType_AggZero)
{ {
auto aggZero = (BfConstant*)fromConst; auto aggZero = (BfConstant*)fromConst;
@ -783,7 +789,20 @@ BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type)
{ {
BfTypeOf_Const* typeOf = mTempAlloc.Alloc<BfTypeOf_Const>(); BfTypeOf_Const* typeOf = mTempAlloc.Alloc<BfTypeOf_Const>();
typeOf->mConstType = BfConstType_TypeOf; typeOf->mConstType = BfConstType_TypeOf;
typeOf->mType = type;
auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(typeOf));
#ifdef CHECK_CONSTHOLDER
irValue.mHolder = this;
#endif
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->mType = type;
typeOf->mTypeData = typeData;
auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(typeOf)); auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(typeOf));
#ifdef CHECK_CONSTHOLDER #ifdef CHECK_CONSTHOLDER
irValue.mHolder = this; irValue.mHolder = this;
@ -1949,11 +1968,18 @@ void BfIRBuilder::Write(const BfIRValue& irValue)
{ {
Write(constant->mInt64); Write(constant->mInt64);
} }
break;
case (int)BfConstType_TypeOf:
{
auto typeofConst = (BfTypeOf_Const*)constant;
Write(MapType(typeofConst->mType, BfIRPopulateType_Identity));
}
break; break;
case (int)BfConstType_Undef: case (int)BfConstType_TypeOf_WithData:
{ {
auto undefConst = (BfConstantUndef*)constant; auto typeofConst = (BfTypeOf_WithData_Const*)constant;
Write(undefConst->mType); Write(MapType(typeofConst->mType, BfIRPopulateType_Identity));
Write(typeofConst->mTypeData);
} }
break; break;
default: default:
@ -4476,6 +4502,12 @@ BfIRValue BfIRBuilder::CreateGlobalStringPtr(const StringImpl& str)
return retVal; 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) BfIRBlock BfIRBuilder::CreateBlock(const StringImpl& name, bool addNow)
{ {
if (addNow) if (addNow)

View file

@ -120,6 +120,7 @@ enum BfConstType
BfConstType_PtrToInt, BfConstType_PtrToInt,
BfConstType_IntToPtr, BfConstType_IntToPtr,
BfConstType_TypeOf, BfConstType_TypeOf,
BfConstType_TypeOf_WithData,
BfConstType_AggZero, BfConstType_AggZero,
BfConstType_Agg, BfConstType_Agg,
BfConstType_ArrayZero, BfConstType_ArrayZero,
@ -235,6 +236,7 @@ enum BfIRCmd : uint8
BfIRCmd_GlobalVar_SetAlignment, BfIRCmd_GlobalVar_SetAlignment,
BfIRCmd_GlobalVar_SetStorageKind, BfIRCmd_GlobalVar_SetStorageKind,
BfIRCmd_GlobalStringPtr, BfIRCmd_GlobalStringPtr,
BfIRCmd_SetReflectTypeData,
BfIRCmd_CreateBlock, BfIRCmd_CreateBlock,
BfIRCmd_MaybeChainNewBlock, BfIRCmd_MaybeChainNewBlock,
@ -771,6 +773,14 @@ struct BfTypeOf_Const
{ {
BfConstType mConstType; BfConstType mConstType;
BfType* mType; BfType* mType;
BfIRValue mTypeData;
};
struct BfTypeOf_WithData_Const
{
BfConstType mConstType;
BfType* mType;
BfIRValue mTypeData;
}; };
struct BfConstant struct BfConstant
@ -906,6 +916,7 @@ public:
BfIRValue CreateConstArrayZero(BfIRType type, int count); BfIRValue CreateConstArrayZero(BfIRType type, int count);
BfIRValue CreateConstArrayZero(int count); BfIRValue CreateConstArrayZero(int count);
BfIRValue CreateTypeOf(BfType* type); BfIRValue CreateTypeOf(BfType* type);
BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData);
BfIRValue GetUndefConstValue(BfIRType type); BfIRValue GetUndefConstValue(BfIRType type);
}; };
@ -1199,6 +1210,7 @@ public:
void GlobalVar_SetAlignment(BfIRValue globalVar, int alignment); void GlobalVar_SetAlignment(BfIRValue globalVar, int alignment);
void GlobalVar_SetStorageKind(BfIRValue globalVar, BfIRStorageKind storageKind); void GlobalVar_SetStorageKind(BfIRValue globalVar, BfIRStorageKind storageKind);
BfIRValue CreateGlobalStringPtr(const StringImpl& str); BfIRValue CreateGlobalStringPtr(const StringImpl& str);
void SetReflectTypeData(BfIRType type, BfIRValue globalVar);
BfIRBlock CreateBlock(const StringImpl& name, bool addNow = false); BfIRBlock CreateBlock(const StringImpl& name, bool addNow = false);
BfIRBlock MaybeChainNewBlock(const StringImpl& name); // Creates new block if current block isn't empty 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); llvmValue = llvm::UndefValue::get(type);
return; 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; bool isSigned;
llvm::Type* llvmConstType = GetLLVMType(typeCode, 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()))); SetResult(curId, mIRBuilder->CreateGlobalStringPtr(llvm::StringRef(str.c_str(), str.length())));
} }
break; break;
case BfIRCmd_SetReflectTypeData:
{
CMD_PARAM(llvm::Type*, type);
CMD_PARAM(llvm::Value*, value);
mReflectDataMap[type] = value;
}
break;
case BfIRCmd_CreateBlock: case BfIRCmd_CreateBlock:
{ {
CMD_PARAM(String, name); CMD_PARAM(String, name);

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -3,6 +3,7 @@
#include "BfCompiler.h" #include "BfCompiler.h"
#include "BfSystem.h" #include "BfSystem.h"
#include "BfParser.h" #include "BfParser.h"
#include "BfReducer.h"
#include "BfCodeGen.h" #include "BfCodeGen.h"
#include "BfExprEvaluator.h" #include "BfExprEvaluator.h"
#include <fcntl.h> #include <fcntl.h>
@ -17,6 +18,7 @@
#include "BfFixits.h" #include "BfFixits.h"
#include "BfIRCodeGen.h" #include "BfIRCodeGen.h"
#include "BfDefBuilder.h" #include "BfDefBuilder.h"
#include "CeMachine.h"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -1931,6 +1933,177 @@ void BfModule::SetTypeOptions(BfTypeInstance* typeInstance)
typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true); 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) void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
{ {
auto typeInstance = resolvedTypeRef->ToTypeInstance(); auto typeInstance = resolvedTypeRef->ToTypeInstance();
@ -1991,7 +2164,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize; resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize;
} }
BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size())); BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mTypeDef->mHasEmitMembers));
typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size()); typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size());
for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++) for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++)
{ {
@ -2807,9 +2980,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
BF_ASSERT(!typeInstance->mNeedsMethodProcessing); BF_ASSERT(!typeInstance->mNeedsMethodProcessing);
if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces) if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces)
typeInstance->mDefineState = BfTypeDefineState_HasInterfaces; typeInstance->mDefineState = BfTypeDefineState_HasInterfaces;
for (auto& validateEntry : deferredTypeValidateList) for (auto& validateEntry : deferredTypeValidateList)
{ {
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, mIgnoreErrors | validateEntry.mIgnoreErrors); SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, mIgnoreErrors | validateEntry.mIgnoreErrors);
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false); ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
} }
@ -2858,7 +3031,28 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (typeInstance->mTypeOptionsIdx == -2) if (typeInstance->mTypeOptionsIdx == -2)
SetTypeOptions(typeInstance); 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) if (populateType <= BfPopulateType_AllowStaticMethods)
return; 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()) if (_CheckTypeDone())
@ -3670,7 +3902,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
member->mRefCount++; member->mRefCount++;
} }
typeInstance->mDefineState = BfTypeDefineState_Defined; if (typeInstance->mDefineState < BfTypeDefineState_Defined)
{
typeInstance->mDefineState = BfTypeDefineState_Defined;
if (!typeInstance->IsBoxed())
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeDone, NULL);
}
if (typeInstance->mTypeFailed) if (typeInstance->mTypeFailed)
mHadBuildError = true; mHadBuildError = true;
@ -3832,7 +4069,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
int64 min = 0; int64 min = 0;
int64 max = 0; int64 max = 0;
bool isFirst = false; bool isFirst = true;
if (typeInstance->mTypeInfoEx == NULL) if (typeInstance->mTypeInfoEx == NULL)
typeInstance->mTypeInfoEx = new BfTypeInfoEx(); typeInstance->mTypeInfoEx = new BfTypeInfoEx();
@ -4310,20 +4547,19 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
continue; continue;
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_InWorkList) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_InWorkList)
continue; continue;
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
continue;
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Referenced) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Referenced)
continue; continue;
if (isFailedType) if (isFailedType)
{ {
// We don't want method decls from failed generic types to clog up our type system // We don't want method decls from failed generic types to clog up our type system
continue; continue;
} }
// This should still be set to the default value BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) ||
BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) || (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl)); (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference));
if ((isBoxed) && (!methodDef->mIsVirtual)) if ((isBoxed) && (!methodDef->mIsVirtual))
{ {
@ -4351,12 +4587,11 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if ((methodDef->mName == BF_METHODNAME_DYNAMICCAST) && (typeInstance->IsValueType())) if ((methodDef->mName == BF_METHODNAME_DYNAMICCAST) && (typeInstance->IsValueType()))
continue; // This is just a placeholder for boxed types continue; // This is just a placeholder for boxed types
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
bool doAlwaysInclude = false;
if (wantsOnDemandMethods) if (wantsOnDemandMethods)
{ {
bool implRequired = false; bool implRequired = false;
bool declRequired = false; bool declRequired = false;
@ -4452,9 +4687,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
} }
if (!implRequired) if (!implRequired)
{ {
BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet); if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
{ {
if (!mIsScratchModule) if (!mIsScratchModule)
mOnDemandMethodCount++; mOnDemandMethodCount++;
@ -4462,19 +4696,41 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (!declRequired) if (!declRequired)
{ {
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference; methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
continue; continue;
} }
else else
{ {
if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl; methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
} }
VerifyOnDemandMethods(); 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);
}
}
} }
BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount); BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount);
@ -5480,7 +5736,7 @@ BfPrimitiveType* BfModule::GetPrimitiveType(BfTypeCode typeCode)
BfIRType BfModule::GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2) BfIRType BfModule::GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2)
{ {
BF_ASSERT(!mIsConstModule); BF_ASSERT(!mIsComptimeModule);
BF_ASSERT(loweredTypeCode != BfTypeCode_None); BF_ASSERT(loweredTypeCode != BfTypeCode_None);
if (loweredTypeCode2 == BfTypeCode_None) if (loweredTypeCode2 == BfTypeCode_None)

View file

@ -341,6 +341,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
mAwaitingDelete = false; mAwaitingDelete = false;
mScanOnly = false; mScanOnly = false;
mCompleteParse = false; mCompleteParse = false;
mIsEmitted = false;
mJumpTable = NULL; mJumpTable = NULL;
mProject = bfProject; mProject = bfProject;
mPassInstance = NULL; mPassInstance = NULL;
@ -525,6 +526,8 @@ void BfParser::SetSource(const char* data, int length)
canCache = false; canCache = false;
if (mProject == NULL) if (mProject == NULL)
canCache = false; canCache = false;
if (mIsEmitted)
canCache = false;
uint64 cacheHash = 0; uint64 cacheHash = 0;
if (canCache) if (canCache)
@ -3447,8 +3450,11 @@ void BfParser::Parse(BfPassInstance* passInstance)
{ {
BP_ZONE_F("BfParser::Parse %s", mFileName.c_str()); BP_ZONE_F("BfParser::Parse %s", mFileName.c_str());
mSyntaxToken = BfSyntaxToken_None;
mPassInstance = passInstance; mPassInstance = passInstance;
int startIdx = mSrcIdx;
if (mUsingCache) if (mUsingCache)
{ {
mRootNode = mParserData->mRootNode; mRootNode = mParserData->mRootNode;
@ -3476,7 +3482,7 @@ void BfParser::Parse(BfPassInstance* passInstance)
mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first); 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) if (mJumpTable[i].mCharIdx == 0)
mJumpTable[i] = mJumpTable[i - 1]; 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) void BfParser::GenerateAutoCompleteFrom(int srcPosition)
{ {
BfSourcePositionFinder posFinder(this, srcPosition); BfSourcePositionFinder posFinder(this, srcPosition);

View file

@ -81,7 +81,7 @@ public:
Dictionary<int, BfParserWarningEnabledChange> mWarningEnabledChanges; Dictionary<int, BfParserWarningEnabledChange> mWarningEnabledChanges;
std::set<int> mUnwarns; std::set<int> mUnwarns;
bool mFailed; // Don't cache if there's a warning or an error bool mFailed; // Don't cache if there's a warning or an error
bool mDidReduce; bool mDidReduce;
public: public:
BfParserData(); BfParserData();
@ -157,6 +157,7 @@ public:
bool mQuickCompatMode; bool mQuickCompatMode;
bool mScanOnly; bool mScanOnly;
bool mCompleteParse; bool mCompleteParse;
bool mIsEmitted;
BfLineStartEntry* mJumpTable; BfLineStartEntry* mJumpTable;
int mJumpTableSize; int mJumpTableSize;
int mOrigSrcLength; int mOrigSrcLength;
@ -231,6 +232,7 @@ public:
void Parse(BfPassInstance* passInstance); void Parse(BfPassInstance* passInstance);
int GetCharIdAtIndex(int findIndex); int GetCharIdAtIndex(int findIndex);
virtual void Close() override; virtual void Close() override;
virtual void HadSrcRealloc() override;
void GenerateAutoCompleteFrom(int srcPosition); void GenerateAutoCompleteFrom(int srcPosition);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -679,6 +679,42 @@ void BfTypeDef::FreeMembers()
mIsNextRevision = false; 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() void BfTypeDef::PopulateMemberSets()
{ {
if ((!mMethodSet.IsEmpty()) || (!mFieldSet.IsEmpty()) || (!mPropertySet.IsEmpty())) 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() BfTypeDef::~BfTypeDef()
{ {
BfLogSysM("BfTypeDef::~BfTypeDef %08X\n", this); BfLogSysM("BfTypeDef::~BfTypeDef %08X\n", this);
@ -732,6 +775,12 @@ BfTypeDef::~BfTypeDef()
mSource->mRefCount--; mSource->mRefCount--;
BF_ASSERT(mSource->mRefCount >= 0); BF_ASSERT(mSource->mRefCount >= 0);
} }
if (mEmitParser != NULL)
{
mEmitParser->mRefCount--;
BF_ASSERT(mEmitParser->mRefCount >= 0);
}
} }
BfSource* BfTypeDef::GetLastSource() BfSource* BfTypeDef::GetLastSource()
@ -1533,6 +1582,8 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf
if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true)) if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true))
return NULL; return NULL;
mWarnIdx++;
TrimSourceRange(bfSource, srcIdx, srcLen); TrimSourceRange(bfSource, srcIdx, srcLen);
BfError* errorVal = new BfError(); 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) BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning)
{ {
mWarnIdx++;
mLastWasAdded = false; mLastWasAdded = false;
mLastWasDisplayed = (int)mErrors.size() <= sMaxDisplayErrors; mLastWasDisplayed = (int)mErrors.size() <= sMaxDisplayErrors;
if (!mLastWasDisplayed) if (!mLastWasDisplayed)
@ -1577,6 +1629,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAs
{ {
BP_ZONE("BfPassInstance::Warn"); BP_ZONE("BfPassInstance::Warn");
mWarnIdx++;
mLastWasAdded = false; mLastWasAdded = false;
mLastWasDisplayed = (int)mErrors.size() <= sMaxErrors; mLastWasDisplayed = (int)mErrors.size() <= sMaxErrors;
if (!mLastWasDisplayed) if (!mLastWasDisplayed)
@ -1638,9 +1691,9 @@ BfMoreInfo* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfS
return NULL; return NULL;
} }
BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info) BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info, bool forceQueue)
{ {
if (!mLastWasDisplayed) if ((!mLastWasDisplayed) || (forceQueue))
{ {
if (mLastWasAdded) 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); 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; bool setDeclaringType = !typeDef->mIsCombinedPartial;
auto nextTypeDef = typeDef->mNextRevision; auto nextTypeDef = typeDef->mNextRevision;
@ -2651,7 +2706,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
typeDef->mTypeCode = nextTypeDef->mTypeCode; typeDef->mTypeCode = nextTypeDef->mTypeCode;
typeDef->mIsAlwaysInclude = nextTypeDef->mIsAlwaysInclude; typeDef->mIsAlwaysInclude = nextTypeDef->mIsAlwaysInclude;
typeDef->mIsNoDiscard = nextTypeDef->mIsNoDiscard; typeDef->mIsNoDiscard = nextTypeDef->mIsNoDiscard;
typeDef->mIsPartial = nextTypeDef->mIsPartial; typeDef->mIsPartial = nextTypeDef->mIsPartial;
typeDef->mIsExplicitPartial = nextTypeDef->mIsExplicitPartial; typeDef->mIsExplicitPartial = nextTypeDef->mIsExplicitPartial;
//mPartialUsed //mPartialUsed
@ -2663,6 +2718,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
typeDef->mIsConcrete = nextTypeDef->mIsConcrete; typeDef->mIsConcrete = nextTypeDef->mIsConcrete;
typeDef->mIsStatic = nextTypeDef->mIsStatic; typeDef->mIsStatic = nextTypeDef->mIsStatic;
typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor;
typeDef->mHasCEOnCompile = nextTypeDef->mHasCEOnCompile;
typeDef->mHasCtorNoBody = nextTypeDef->mHasCtorNoBody; typeDef->mHasCtorNoBody = nextTypeDef->mHasCtorNoBody;
typeDef->mHasOverrideMethods = nextTypeDef->mHasOverrideMethods; typeDef->mHasOverrideMethods = nextTypeDef->mHasOverrideMethods;
typeDef->mHasExtensionMethods = nextTypeDef->mHasExtensionMethods; typeDef->mHasExtensionMethods = nextTypeDef->mHasExtensionMethods;
@ -2722,7 +2778,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
delete nextTypeDef; delete nextTypeDef;
typeDef->mNextRevision = NULL; typeDef->mNextRevision = NULL;
typeDef->mDefState = BfTypeDef::DefState_Defined; typeDef->mDefState = BfTypeDef::DefState_Defined;
VerifyTypeDef(typeDef); VerifyTypeDef(typeDef);
} }
@ -2771,6 +2827,8 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody; typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody;
typeDef->mHasExtensionMethods = partialTypeDef->mHasExtensionMethods; typeDef->mHasExtensionMethods = partialTypeDef->mHasExtensionMethods;
typeDef->mHasOverrideMethods = partialTypeDef->mHasOverrideMethods; typeDef->mHasOverrideMethods = partialTypeDef->mHasOverrideMethods;
typeDef->mIsAlwaysInclude = partialTypeDef->mIsAlwaysInclude;
typeDef->mHasCEOnCompile = partialTypeDef->mHasCEOnCompile;
for (auto generic : partialTypeDef->mGenericParamDefs) for (auto generic : partialTypeDef->mGenericParamDefs)
{ {
@ -2806,6 +2864,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
typeDef->mIsConcrete |= partialTypeDef->mIsConcrete; typeDef->mIsConcrete |= partialTypeDef->mIsConcrete;
typeDef->mIsStatic |= partialTypeDef->mIsStatic; typeDef->mIsStatic |= partialTypeDef->mIsStatic;
typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor; typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor;
typeDef->mHasCEOnCompile |= partialTypeDef->mHasCEOnCompile;
typeDef->mHasExtensionMethods |= partialTypeDef->mHasExtensionMethods; typeDef->mHasExtensionMethods |= partialTypeDef->mHasExtensionMethods;
typeDef->mHasOverrideMethods |= partialTypeDef->mHasOverrideMethods; typeDef->mHasOverrideMethods |= partialTypeDef->mHasOverrideMethods;
typeDef->mProtection = BF_MIN(typeDef->mProtection, partialTypeDef->mProtection); 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); BfLogSys(this, "Deleting Old Parser: %p New Parser: %p\n", bfParser, bfParser->mNextRevision);
mParsers.RemoveAt(i);
i--;
mDataLock.Unlock(); mDataLock.Unlock();
delete bfParser; delete bfParser;
mDataLock.Lock(); 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 BfAlwaysIncludeFlag_All = BfAlwaysIncludeFlag_Type | BfAlwaysIncludeFlag_IncludeAllMethods | BfAlwaysIncludeFlag_AssumeInstantiated
}; };
enum BfCEOnCompileKind : uint8
{
BfCEOnCompileKind_None,
BfCEOnCompileKind_TypeInit,
BfCEOnCompileKind_TypeDone
};
enum BfPlatformType enum BfPlatformType
{ {
BfPlatformType_Unknown, BfPlatformType_Unknown,
@ -740,6 +747,14 @@ enum BfCommutableKind : int8
BfCommutableKind_Reverse, BfCommutableKind_Reverse,
}; };
enum BfComptimeFlags : int8
{
BfComptimeFlag_None,
BfComptimeFlag_Comptime = 1,
BfComptimeFlag_OnlyFromComptime = 2,
BfComptimeFlag_ConstEval = 4
};
class BfMethodDef : public BfMemberDef class BfMethodDef : public BfMemberDef
{ {
public: public:
@ -774,7 +789,7 @@ public:
bool mIsNoSplat; bool mIsNoSplat;
bool mIsNoReflect; bool mIsNoReflect;
bool mIsSkipCall; bool mIsSkipCall;
bool mIsConstEval; bool mHasComptime;
bool mIsOperator; bool mIsOperator;
bool mIsExtern; bool mIsExtern;
bool mIsNoDiscard; bool mIsNoDiscard;
@ -803,7 +818,7 @@ public:
mIsNoSplat = false; mIsNoSplat = false;
mIsNoReflect = false; mIsNoReflect = false;
mIsSkipCall = false; mIsSkipCall = false;
mIsConstEval = false; mHasComptime = false;
mIsOperator = false; mIsOperator = false;
mIsExtern = false; mIsExtern = false;
mIsNoDiscard = false; mIsNoDiscard = false;
@ -914,11 +929,12 @@ public:
public: public:
BfTypeDef* mNextRevision; BfTypeDef* mNextRevision;
BfSystem* mSystem; BfSystem* mSystem;
BfProject* mProject; BfProject* mProject;
BfTypeDeclaration* mTypeDeclaration; BfTypeDeclaration* mTypeDeclaration;
BfSource* mSource; BfSource* mSource;
BfParser* mEmitParser;
DefState mDefState; DefState mDefState;
Val128 mSignatureHash; // Data, methods, etc Val128 mSignatureHash; // Data, methods, etc
Val128 mFullHash; Val128 mFullHash;
@ -953,7 +969,7 @@ public:
int mPartialIdx; int mPartialIdx;
int mNestDepth; int mNestDepth;
int mDupDetectedRevision; // Error state int mDupDetectedRevision; // Error state
BfTypeCode mTypeCode; BfTypeCode mTypeCode;
bool mIsAlwaysInclude; bool mIsAlwaysInclude;
bool mIsNoDiscard; bool mIsNoDiscard;
bool mIsPartial; bool mIsPartial;
@ -966,6 +982,7 @@ public:
bool mIsAbstract; bool mIsAbstract;
bool mIsConcrete; bool mIsConcrete;
bool mIsStatic; bool mIsStatic;
bool mHasCEOnCompile;
bool mHasAppendCtor; bool mHasAppendCtor;
bool mHasCtorNoBody; bool mHasCtorNoBody;
bool mHasExtensionMethods; bool mHasExtensionMethods;
@ -973,6 +990,7 @@ public:
bool mIsOpaque; bool mIsOpaque;
bool mIsNextRevision; bool mIsNextRevision;
bool mInDeleteQueue; bool mInDeleteQueue;
bool mHasEmitMembers;
public: public:
BfTypeDef() BfTypeDef()
@ -988,7 +1006,7 @@ public:
mNameEx = NULL; mNameEx = NULL;
mSystem = NULL; mSystem = NULL;
mProject = NULL; mProject = NULL;
mTypeCode = BfTypeCode_None; mTypeCode = BfTypeCode_None;
mIsAlwaysInclude = false; mIsAlwaysInclude = false;
mIsNoDiscard = false; mIsNoDiscard = false;
mIsExplicitPartial = false; mIsExplicitPartial = false;
@ -996,6 +1014,7 @@ public:
mIsCombinedPartial = false; mIsCombinedPartial = false;
mTypeDeclaration = NULL; mTypeDeclaration = NULL;
mSource = NULL; mSource = NULL;
mEmitParser = NULL;
mDefState = DefState_New; mDefState = DefState_New;
mHash = 0; mHash = 0;
mPartialIdx = -1; mPartialIdx = -1;
@ -1005,6 +1024,7 @@ public:
mIsFunction = false; mIsFunction = false;
mIsClosure = false; mIsClosure = false;
mIsStatic = false; mIsStatic = false;
mHasCEOnCompile = false;
mHasAppendCtor = false; mHasAppendCtor = false;
mHasCtorNoBody = false; mHasCtorNoBody = false;
mHasExtensionMethods = false; mHasExtensionMethods = false;
@ -1013,12 +1033,13 @@ public:
mPartialUsed = false; mPartialUsed = false;
mIsNextRevision = false; mIsNextRevision = false;
mInDeleteQueue = false; mInDeleteQueue = false;
mHasEmitMembers = false;
mDupDetectedRevision = -1; mDupDetectedRevision = -1;
mNestDepth = 0; mNestDepth = 0;
mOuterType = NULL; mOuterType = NULL;
mTypeDeclaration = NULL; mTypeDeclaration = NULL;
mDtorDef = NULL; mDtorDef = NULL;
mNextRevision = NULL; mNextRevision = NULL;
mProtection = BfProtection_Public; mProtection = BfProtection_Public;
} }
@ -1026,7 +1047,9 @@ public:
bool IsGlobalsContainer(); bool IsGlobalsContainer();
void Reset(); void Reset();
void FreeMembers(); void FreeMembers();
void ClearEmitted();
void PopulateMemberSets(); void PopulateMemberSets();
void ClearMemberSets();
void RemoveGenericParamDef(BfGenericParamDef* genericParamDef); void RemoveGenericParamDef(BfGenericParamDef* genericParamDef);
int GetSelfGenericParamCount(); int GetSelfGenericParamCount();
String ToString(); String ToString();
@ -1284,12 +1307,13 @@ public:
BfSystem* mSystem; BfSystem* mSystem;
bool mTrimMessagesToCursor; bool mTrimMessagesToCursor;
int mFailedIdx; int mFailedIdx;
int mWarnIdx;
Dictionary<BfSourceData*, String> mSourceFileNameMap; Dictionary<BfSourceData*, String> mSourceFileNameMap;
HashSet<BfErrorEntry> mErrorSet; HashSet<BfErrorEntry> mErrorSet;
Array<BfError*> mErrors; Array<BfError*> mErrors;
int mIgnoreCount; int mIgnoreCount;
int mWarningCount; int mWarningCount;
int mDeferredErrorCount; int mDeferredErrorCount;
Deque<String> mOutStream; Deque<String> mOutStream;
bool mLastWasDisplayed; bool mLastWasDisplayed;
@ -1303,11 +1327,12 @@ public:
{ {
mTrimMessagesToCursor = false; mTrimMessagesToCursor = false;
mFailedIdx = 0; mFailedIdx = 0;
mWarnIdx = 0;
mSystem = bfSystem; mSystem = bfSystem;
mLastWasDisplayed = false; mLastWasDisplayed = false;
mLastWasAdded = false; mLastWasAdded = false;
mClassifierPassId = 0; mClassifierPassId = 0;
mWarningCount = 0; mWarningCount = 0;
mDeferredErrorCount = 0; mDeferredErrorCount = 0;
mIgnoreCount = 0; mIgnoreCount = 0;
mFilterErrorsTo = NULL; mFilterErrorsTo = NULL;
@ -1336,7 +1361,7 @@ public:
BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode); 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* 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* MoreInfo(const StringImpl& info, BfAstNode* refNode);
BfMoreInfo* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode); BfMoreInfo* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode);

View file

@ -728,8 +728,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
CeStaticFieldInfo* staticFieldInfoPtr = NULL; CeStaticFieldInfo* staticFieldInfoPtr = NULL;
if (mCeMachine->mStaticFieldMap.TryGetValue(globalVar->mName, &staticFieldInfoPtr)) if (mCeMachine->mStaticFieldMap.TryGetValue(globalVar->mName, &staticFieldInfoPtr))
{ {
CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr; CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr;
int* staticFieldTableIdxPtr = NULL; int* staticFieldTableIdxPtr = NULL;
if (mStaticFieldMap.TryAdd(globalVar, NULL, &staticFieldTableIdxPtr)) if (mStaticFieldMap.TryAdd(globalVar, NULL, &staticFieldTableIdxPtr))
{ {
@ -1190,8 +1189,6 @@ void CeBuilder::Build()
bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation()); bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation());
int dependentGenericStartIdx = 0; int dependentGenericStartIdx = 0;
if (methodInstance->mMethodInfoEx != NULL)
dependentGenericStartIdx = (int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size();
if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) || if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod)))) ((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod))))
{ {
@ -2646,13 +2643,17 @@ CeMachine::CeMachine(BfCompiler* compiler)
mCurFunctionId = 0; mCurFunctionId = 0;
mRevisionExecuteTime = 0; mRevisionExecuteTime = 0;
mCurTargetSrc = NULL; mCurTargetSrc = NULL;
mCurBuilder = NULL;
mPreparingFunction = NULL; mPreparingFunction = NULL;
mCurEvalFlags = CeEvalFlags_None;
mCurFrame = NULL;
mCurModule = NULL; mCurModule = NULL;
mCurMethodInstance = NULL; mCurMethodInstance = NULL;
mCurExpectingType = NULL; mCurExpectingType = NULL;
mCurEmitContext = NULL;
mHeap = NULL; mHeap = NULL;
mStringCharsOffset = -1; mStringCharsOffset = -1;
mAppendAllocInfo = NULL; mAppendAllocInfo = NULL;
} }
CeMachine::~CeMachine() CeMachine::~CeMachine()
@ -2689,19 +2690,25 @@ CeMachine::~CeMachine()
BfError* CeMachine::Fail(const StringImpl& error) 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) if (bfError == NULL)
return NULL; return NULL;
mCompiler->mPassInstance->MoreInfo(error); mCompiler->mPassInstance->MoreInfo(error, mCeModule->mCompiler->GetAutoComplete() != NULL);
return bfError; return bfError;
} }
BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) 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) if (bfError == NULL)
return NULL; return NULL;
if ((mCurEvalFlags & CeEvalFlags_DeferIfNotOnlyError) != 0)
{
if (mCurModule->mHadBuildError)
bfError->mIsDeferred = true;
}
auto passInstance = mCompiler->mPassInstance; auto passInstance = mCompiler->mPassInstance;
for (int stackIdx = mCallStack.size(); stackIdx >= 0; stackIdx--) 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; 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) if (emitEntry != NULL)
err += StrFormat(" at line% d:%d in %s", emitEntry->mLine + 1, emitEntry->mColumn + 1, ceFunction->mFiles[emitEntry->mFile].c_str()); 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)) if ((moreInfo != NULL) && (emitEntry != NULL))
{ {
BfErrorLocation* location = new BfErrorLocation(); BfErrorLocation* location = new BfErrorLocation();
@ -2785,7 +2792,7 @@ void CeMachine::Init()
mCeModule = new BfModule(mCompiler->mContext, "__constEval"); mCeModule = new BfModule(mCompiler->mContext, "__constEval");
mCeModule->mIsSpecialModule = true; mCeModule->mIsSpecialModule = true;
//mCeModule->mIsScratchModule = true; //mCeModule->mIsScratchModule = true;
mCeModule->mIsConstModule = true; mCeModule->mIsComptimeModule = true;
//mCeModule->mIsReified = true; //mCeModule->mIsReified = true;
if (mCompiler->mIsResolveOnly) if (mCompiler->mIsResolveOnly)
mCeModule->mIsReified = true; mCeModule->mIsReified = true;
@ -2882,7 +2889,8 @@ addr_ce CeMachine::GetReflectType(int typeId)
if (bfType == NULL) if (bfType == NULL)
return 0; return 0;
mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods); if (bfType->mDefineState != BfTypeDefineState_CETypeInit)
mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
Dictionary<int, int> usedStringMap; Dictionary<int, int> usedStringMap;
auto irData = mCeModule->CreateTypeData(bfType, usedStringMap, true, true, true, false); auto irData = mCeModule->CreateTypeData(bfType, usedStringMap, true, true, true, false);
@ -2991,6 +2999,30 @@ void CeMachine::PrepareConstStructEntry(CeConstStructData& constEntry)
constEntry.mBindExecuteId = mExecuteId; 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() BeContext* CeMachine::GetBeContext()
{ {
if (mCeModule == NULL) 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) void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
{ {
ceFunctionInfo->mRefCount--; 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; return false;
} }
@ -3489,7 +3534,6 @@ CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constV
return CeErrorKind_None; return CeErrorKind_None;
} }
#define CE_CREATECONST_CHECKPTR(PTR, SIZE) \ #define CE_CREATECONST_CHECKPTR(PTR, SIZE) \
if ((((uint8*)(PTR) - memStart) - 0x10000) + (SIZE) > (memSize - 0x10000)) \ if ((((uint8*)(PTR) - memStart) - 0x10000) + (SIZE) > (memSize - 0x10000)) \
{ \ { \
@ -3829,8 +3873,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
uint8* stackPtr = startStackPtr; uint8* stackPtr = startStackPtr;
uint8* framePtr = startFramePtr; uint8* framePtr = startFramePtr;
bool needsFunctionIds = mCeModule->mSystem->mPtrSize != 8; 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 = [&]() auto _GetCurFrame = [&]()
{ {
@ -3973,12 +4019,30 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
handled = true; handled = true;
return 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) else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep)
{ {
int32 sleepMS = *(int32*)((uint8*)stackPtr); int32 sleepMS = *(int32*)((uint8*)stackPtr);
while (sleepMS > 0) while (sleepMS > 0)
{ {
if (*cancelPtr) if (*fastFinishPtr)
break; break;
if (sleepMS > 200) if (sleepMS > 200)
@ -4104,9 +4168,9 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (!checkFunction->mFailed) if (!checkFunction->mFailed)
return true; 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())) 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; return false;
}; };
@ -4124,9 +4188,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
while (true) while (true)
{ {
if (*cancelPtr) if (*fastFinishPtr)
{ {
_Fail("Compilation cancelled"); if (*cancelingPtr)
_Fail("Comptime evaluation canceled");
return false; return false;
} }
@ -4576,10 +4641,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (staticFieldInfo->mAddr == 0) if (staticFieldInfo->mAddr == 0)
{ {
if (ceStaticFieldEntry.mSize < 0)
_Fail(StrFormat("Reference to unsized global variable '%s'", ceStaticFieldEntry.mName.c_str()));
CE_CHECKALLOC(ceStaticFieldEntry.mSize); CE_CHECKALLOC(ceStaticFieldEntry.mSize);
uint8* ptr = CeMalloc(ceStaticFieldEntry.mSize); uint8* ptr = CeMalloc(ceStaticFieldEntry.mSize);
_FixVariables(); _FixVariables();
memset(ptr, 0, ceStaticFieldEntry.mSize); if (ceStaticFieldEntry.mSize > 0)
memset(ptr, 0, ceStaticFieldEntry.mSize);
staticFieldInfo->mAddr = (addr_ce)(ptr - memStart); staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
} }
@ -4641,14 +4710,22 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction; callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction;
if (!callEntry.mFunction->mInitialized) if (!callEntry.mFunction->mInitialized)
{ {
auto curFrame = _GetCurFrame();
SetAndRestoreValue<CeFrame*> prevFrame(mCurFrame, &curFrame);
PrepareFunction(callEntry.mFunction, NULL); PrepareFunction(callEntry.mFunction, NULL);
} }
callEntry.mBindRevision = mRevision; callEntry.mBindRevision = mRevision;
} }
BF_ASSERT(memStart == mMemory.mVals); BF_ASSERT(memStart == mMemory.mVals);
auto callFunction = callEntry.mFunction; auto callFunction = callEntry.mFunction;
if (callFunction->mMethodInstance->mMethodDef->mIsLocalMethod)
{
NOP;
}
if (needsFunctionIds) if (needsFunctionIds)
*(int32*)(framePtr + resultFrameIdx) = callFunction->mId; *(int32*)(framePtr + resultFrameIdx) = callFunction->mId;
else else
@ -4678,7 +4755,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CE_CHECKADDR(valueAddr, sizeof(int32)); CE_CHECKADDR(valueAddr, sizeof(int32));
int32 objTypeId = *(int32*)(memStart + valueAddr); 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()) if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods); mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod; auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod;
@ -4702,23 +4786,26 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CE_CHECKADDR(valueAddr, sizeof(int32)); CE_CHECKADDR(valueAddr, sizeof(int32));
int32 objTypeId = *(int32*)(memStart + valueAddr); int32 objTypeId = *(int32*)(memStart + valueAddr);
auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance(); auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance();
if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
BfMethodInstance* methodInstance = NULL; BfMethodInstance* methodInstance = NULL;
auto checkType = valueType; if (valueType != NULL)
while (checkType != NULL)
{ {
for (auto& iface : checkType->mInterfaces) if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
auto checkType = valueType;
while (checkType != NULL)
{ {
if (iface.mInterfaceType == ifaceType) for (auto& iface : checkType->mInterfaces)
{ {
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef; if (iface.mInterfaceType == ifaceType)
break; {
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef;
break;
}
} }
checkType = checkType->mBaseType;
} }
checkType = checkType->mBaseType;
} }
if (methodInstance == NULL) if (methodInstance == NULL)
@ -5305,18 +5392,25 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
auto owner = ceFunction->mMethodInstance->GetOwner(); auto owner = ceFunction->mMethodInstance->GetOwner();
if (owner == mCeModule->mContext->mBfObjectType) if (owner == mCeModule->mContext->mBfObjectType)
{ {
if (methodDef->mName == "ConstEval_GetType") if (methodDef->mName == "Comptime_GetType")
{ {
ceFunction->mFunctionKind = CeFunctionKind_GetReflectType; ceFunction->mFunctionKind = CeFunctionKind_GetReflectType;
} }
} }
else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef)) else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef))
{ {
if (methodDef->mName == "ConstEval_GetTypeById") if (methodDef->mName == "Comptime_GetTypeById")
{ {
ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById; 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)) else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef))
{ {
if (methodDef->mName == "Write") if (methodDef->mName == "Write")
@ -5373,6 +5467,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
ceFunction->mGenerating = true; ceFunction->mGenerating = true;
CeBuilder ceBuilder; CeBuilder ceBuilder;
SetAndRestoreValue<CeBuilder*> prevBuilder(mCurBuilder, &ceBuilder);
ceBuilder.mParentBuilder = parentBuilder; ceBuilder.mParentBuilder = parentBuilder;
ceBuilder.mPtrSize = mCeModule->mCompiler->mSystem->mPtrSize; ceBuilder.mPtrSize = mCeModule->mCompiler->mSystem->mPtrSize;
ceBuilder.mCeMachine = this; ceBuilder.mCeMachine = this;
@ -5534,6 +5629,7 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
// DISABLED // DISABLED
//return BfTypedValue(); //return BfTypedValue();
SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags);
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc); SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module); SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);

View file

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

View file

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

View file

@ -195,6 +195,22 @@ namespace Tests
TI iface = val as TI; 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] [Test]
public static void TestBasics() public static void TestBasics()
{ {