1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Added '->' operator, static indexer fix, RefCounted<T>

This commit is contained in:
Brian Fiete 2022-06-22 08:35:25 -07:00
parent dd7986aaa9
commit abd511a93d
14 changed files with 302 additions and 20 deletions

View file

@ -6,7 +6,7 @@ namespace System
interface IRefCounted interface IRefCounted
{ {
void AddRef(); void AddRef();
void ReleaseRef(); void Release();
} }
class RefCounted : IRefCounted class RefCounted : IRefCounted
@ -63,5 +63,167 @@ namespace System
Debug.Assert(refCount >= 0); Debug.Assert(refCount >= 0);
return refCount; return refCount;
} }
void IRefCounted.Release()
{
ReleaseRef();
}
struct Alloc
{
public void* Alloc(Type type, int size, int align)
{
int sizeAdd = size + Math.Max(align, sizeof(int));
void* data = Internal.Malloc(sizeAdd);
return (uint8*)data + sizeAdd;
}
}
}
class RefCounted<T> : IRefCounted where T : class, delete
{
public T mVal;
public int mRefCount = 1;
public int RefCount => mRefCount;
public T Value => mVal;
protected this()
{
}
protected ~this()
{
Debug.Assert(mRefCount == 0);
delete mVal;
}
[OnCompile(.TypeInit), Comptime]
static void Init()
{
String emitStr = scope .();
for (var methodInfo in typeof(T).GetMethods(.Public))
{
if (methodInfo.IsStatic)
continue;
if (!methodInfo.IsConstructor)
continue;
emitStr.AppendF("public static RefCounted<T> Create(");
methodInfo.GetParamsDecl(emitStr);
emitStr.AppendF(")\n");
emitStr.AppendF("{{\n");
emitStr.AppendF("\treturn new [Friend] RefCountedAppend<T>(");
methodInfo.GetArgsList(emitStr);
emitStr.AppendF(");\n}}\n");
}
Compiler.EmitTypeBody(typeof(Self), emitStr);
}
public static RefCounted<T> Attach(T val)
{
return new Self() { mVal = val };
}
public virtual void DeleteSelf()
{
delete this;
}
public void DeleteUnchecked()
{
mRefCount = 0;
DeleteSelf();
}
public void AddRef()
{
Interlocked.Increment(ref mRefCount);
}
public void Release()
{
int refCount = Interlocked.Decrement(ref mRefCount);
Debug.Assert(refCount >= 0);
if (refCount == 0)
DeleteSelf();
}
public void ReleaseLastRef()
{
int refCount = Interlocked.Decrement(ref mRefCount);
Debug.Assert(refCount == 0);
if (refCount == 0)
DeleteSelf();
}
public int ReleaseRefNoDelete()
{
int refCount = Interlocked.Decrement(ref mRefCount);
Debug.Assert(refCount >= 0);
return refCount;
}
public virtual T Detach()
{
var val = mVal;
mVal = null;
return val;
}
public static T operator->(Self self)
{
return self.mVal;
}
public static T operator implicit(Self self)
{
return self.mVal;
}
}
class RefCountedAppend<T> : RefCounted<T> where T : class, new, delete
{
protected ~this()
{
Debug.Assert(mRefCount == 0);
delete:append mVal;
mVal = null;
}
[OnCompile(.TypeInit), Comptime]
static void Init()
{
String emitStr = scope .();
for (var methodInfo in typeof(T).GetMethods(.Public))
{
if (methodInfo.IsStatic)
continue;
if (!methodInfo.IsConstructor)
continue;
emitStr.AppendF("[AllowAppend]\nprotected this(");
methodInfo.GetParamsDecl(emitStr);
emitStr.AppendF(")\n");
emitStr.AppendF("{{\n");
emitStr.AppendF("\tvar val = append T(");
methodInfo.GetArgsList(emitStr);
emitStr.AppendF(");\n");
emitStr.AppendF("\tmVal = val;\n");
emitStr.AppendF("}}\n");
}
Compiler.EmitTypeBody(typeof(Self), emitStr);
}
public override T Detach()
{
Runtime.FatalError("Can only detach from objects created via RefCounted<T>.Attach");
}
} }
} }

View file

@ -50,6 +50,9 @@ namespace System.Reflection
public bool IsReadOnly => Compiler.IsComptime ? public bool IsReadOnly => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.HasFlag(.ReadOnly) : Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.HasFlag(.ReadOnly) :
mData.mMethodData.[Friend]mFlags.HasFlag(.ReadOnly); mData.mMethodData.[Friend]mFlags.HasFlag(.ReadOnly);
public bool IsStatic => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.HasFlag(.Static) :
mData.mMethodData.[Friend]mFlags.HasFlag(.Static);
public StringView Name => Compiler.IsComptime ? public StringView Name => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetName(mData.mComptimeMethodInstance) : Type.[Friend]Comptime_Method_GetName(mData.mComptimeMethodInstance) :
@ -112,6 +115,19 @@ namespace System.Reflection
} }
} }
public TypeInstance.ParamFlags GetParamFlags(int paramIdx)
{
if (Compiler.IsComptime)
{
return Type.[Friend]Comptime_Method_GetParamInfo(mData.mComptimeMethodInstance, (.)paramIdx).mParamFlags;
}
else
{
Debug.Assert((uint)paramIdx < (uint)mData.mMethodData.mParamCount);
return mData.mMethodData.mParamData[paramIdx].mParamFlags;
}
}
public Result<T> GetParamCustomAttribute<T>(int paramIdx) where T : Attribute public Result<T> GetParamCustomAttribute<T>(int paramIdx) where T : Attribute
{ {
if (Compiler.IsComptime) if (Compiler.IsComptime)
@ -967,19 +983,60 @@ namespace System.Reflection
strBuffer.Append(' '); strBuffer.Append(' ');
strBuffer.Append(mData.mMethodData.mName); strBuffer.Append(mData.mMethodData.mName);
strBuffer.Append('('); strBuffer.Append('(');
int useParamIdx = 0;
for (int paramIdx < mData.mMethodData.mParamCount) for (int paramIdx < mData.mMethodData.mParamCount)
{ {
if (paramIdx > 0)
strBuffer.Append(", ");
let paramData = mData.mMethodData.mParamData[paramIdx]; let paramData = mData.mMethodData.mParamData[paramIdx];
let paramType = Type.[Friend]GetType(paramData.mType); let paramType = Type.[Friend]GetType(paramData.mType);
if (paramData.mParamFlags.HasFlag(.Implicit))
continue;
if (useParamIdx > 0)
strBuffer.Append(", ");
paramType.ToString(strBuffer); paramType.ToString(strBuffer);
strBuffer.Append(' '); strBuffer.Append(' ');
strBuffer.Append(paramData.mName); strBuffer.Append(paramData.mName);
useParamIdx++;
} }
strBuffer.Append(')'); strBuffer.Append(')');
} }
public void GetParamsDecl(String strBuffer)
{
int useParamIdx = 0;
for (int paramIdx < ParamCount)
{
var flag = GetParamFlags(paramIdx);
if (flag.HasFlag(.Implicit))
continue;
if (useParamIdx > 0)
strBuffer.Append(", ");
if (flag.HasFlag(.Params))
strBuffer.Append("params ");
strBuffer.Append(GetParamType(paramIdx));
strBuffer.Append(" ");
strBuffer.Append(GetParamName(paramIdx));
useParamIdx++;
}
}
public void GetArgsList(String strBuffer)
{
int useParamIdx = 0;
for (int paramIdx < ParamCount)
{
var flag = GetParamFlags(paramIdx);
if (flag.HasFlag(.Implicit))
continue;
if (useParamIdx > 0)
strBuffer.Append(", ");
if (flag.HasFlag(.Params))
strBuffer.Append("params ");
strBuffer.Append(GetParamName(paramIdx));
useParamIdx++;
}
}
public struct Enumerator : IEnumerator<MethodInfo> public struct Enumerator : IEnumerator<MethodInfo>
{ {
BindingFlags mBindingFlags; BindingFlags mBindingFlags;

View file

@ -40,7 +40,7 @@ namespace System
[Ordered] [Ordered]
class String : IHashable, IFormattable, IPrintable class String : IHashable, IFormattable, IPrintable
{ {
enum CreateFlags public enum CreateFlags
{ {
None = 0, None = 0,
NullTerminate = 1 NullTerminate = 1

View file

@ -852,7 +852,8 @@ namespace System.Reflection
None = 0, None = 0,
Splat = 1, Splat = 1,
Implicit = 2, Implicit = 2,
AppendIdx = 4 AppendIdx = 4,
Params = 8
} }
[CRepr, AlwaysInclude] [CRepr, AlwaysInclude]

View file

@ -1768,6 +1768,7 @@ const char* Beefy::BfGetOpName(BfUnaryOp unaryOp)
{ {
case BfUnaryOp_None: return ""; case BfUnaryOp_None: return "";
case BfUnaryOp_AddressOf: return "&"; case BfUnaryOp_AddressOf: return "&";
case BfUnaryOp_Arrow: return "->";
case BfUnaryOp_Dereference: return "*"; case BfUnaryOp_Dereference: return "*";
case BfUnaryOp_Negate: return "-"; case BfUnaryOp_Negate: return "-";
case BfUnaryOp_Not: return "!"; case BfUnaryOp_Not: return "!";
@ -1862,6 +1863,8 @@ BfUnaryOp Beefy::BfTokenToUnaryOp(BfToken token)
return BfUnaryOp_Dereference; return BfUnaryOp_Dereference;
case BfToken_Ampersand: case BfToken_Ampersand:
return BfUnaryOp_AddressOf; return BfUnaryOp_AddressOf;
case BfToken_Arrow:
return BfUnaryOp_Arrow;
case BfToken_Minus: case BfToken_Minus:
return BfUnaryOp_Negate; return BfUnaryOp_Negate;
case BfToken_Bang: case BfToken_Bang:

View file

@ -1901,6 +1901,7 @@ enum BfUnaryOp
{ {
BfUnaryOp_None, BfUnaryOp_None,
BfUnaryOp_AddressOf, BfUnaryOp_AddressOf,
BfUnaryOp_Arrow,
BfUnaryOp_Dereference, BfUnaryOp_Dereference,
BfUnaryOp_Negate, BfUnaryOp_Negate,
BfUnaryOp_Not, BfUnaryOp_Not,

View file

@ -1857,6 +1857,14 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken
bool isStatic = false; bool isStatic = false;
BfTypedValue targetValue = LookupTypeRefOrIdentifier(target, &isStatic, (BfEvalExprFlags)(BfEvalExprFlags_IgnoreNullConditional | BfEvalExprFlags_NoCast), expectingType); BfTypedValue targetValue = LookupTypeRefOrIdentifier(target, &isStatic, (BfEvalExprFlags)(BfEvalExprFlags_IgnoreNullConditional | BfEvalExprFlags_NoCast), expectingType);
if ((targetValue) && (dotToken->mToken == BfToken_Arrow))
{
SetAndRestoreValue<bool> prevIgnoreClassifying(mModule->mIsInsideAutoComplete, true);
BfExprEvaluator exprEvaluator(mModule);
auto arrowValue = exprEvaluator.PerformUnaryOperation_TryOperator(targetValue, NULL, BfUnaryOp_Arrow, BfNodeDynCast<BfTokenNode>(dotToken), BfUnaryOpFlag_None);
if (arrowValue)
targetValue = arrowValue;
}
bool hadResults = false; bool hadResults = false;
bool doAsNamespace = true; bool doAsNamespace = true;

View file

@ -2527,8 +2527,7 @@ void BfMethodMatcher::FlushAmbiguityError()
error = mModule->Fail("Ambiguous method call", mTargetSrc); error = mModule->Fail("Ambiguous method call", mTargetSrc);
if (error != NULL) if (error != NULL)
{ {
auto unspecializedType = mModule->GetUnspecializedTypeInstance(mBestMethodTypeInstance); BfMethodInstance* bestMethodInstance = mModule->GetUnspecializedMethodInstance(mBestRawMethodInstance, true);
BfMethodInstance* bestMethodInstance = mModule->GetRawMethodInstance(unspecializedType, mBestMethodDef);
BfTypeVector* typeGenericArguments = NULL; BfTypeVector* typeGenericArguments = NULL;
if (mBestMethodTypeInstance->mGenericTypeInfo != NULL) if (mBestMethodTypeInstance->mGenericTypeInfo != NULL)
typeGenericArguments = &mBestMethodTypeInstance->mGenericTypeInfo->mTypeGenericArguments; typeGenericArguments = &mBestMethodTypeInstance->mGenericTypeInfo->mTypeGenericArguments;
@ -4580,6 +4579,16 @@ void BfExprEvaluator::FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType
mModule->mCompiler->mResolvePassData->mAutoComplete->FixitAddMember(typeInst, fieldType, fieldName, isStatic, mModule->mCurTypeInstance); mModule->mCompiler->mResolvePassData->mAutoComplete->FixitAddMember(typeInst, fieldType, fieldName, isStatic, mModule->mCurTypeInstance);
} }
BfTypedValue BfExprEvaluator::TryArrowLookup(BfTypedValue typedValue, BfTokenNode* arrowToken)
{
auto arrowValue = PerformUnaryOperation_TryOperator(typedValue, NULL, BfUnaryOp_Arrow, arrowToken, BfUnaryOpFlag_None);
if (arrowValue)
return arrowValue;
if (mModule->PreFail())
mModule->Fail(StrFormat("Type '%s' does not contain a '->' operator", mModule->TypeToString(typedValue.mType).c_str()), arrowToken);
return typedValue;
}
BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue target, BfTypeInstance* typeInstance, BfPropertyDef* prop, BfLookupFieldFlags flags, BfCheckedKind checkedKind, bool isInlined) BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue target, BfTypeInstance* typeInstance, BfPropertyDef* prop, BfLookupFieldFlags flags, BfCheckedKind checkedKind, bool isInlined)
{ {
if ((flags & BfLookupFieldFlag_IsAnonymous) == 0) if ((flags & BfLookupFieldFlag_IsAnonymous) == 0)
@ -17635,6 +17644,9 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
} }
thisValue = mResult; thisValue = mResult;
mResult = BfTypedValue(); mResult = BfTypedValue();
if ((thisValue) && (memberRefExpression->mDotToken != NULL) && (memberRefExpression->mDotToken->mToken == BfToken_Arrow))
thisValue = TryArrowLookup(thisValue, memberRefExpression->mDotToken);
} }
else if (auto qualifiedName = BfNodeDynCast<BfQualifiedNameNode>(target)) else if (auto qualifiedName = BfNodeDynCast<BfQualifiedNameNode>(target))
{ {
@ -20795,10 +20807,11 @@ void BfExprEvaluator::DoMemberReference(BfMemberReferenceExpression* memberRefEx
bool isNullCondLookup = (memberRefExpr->mDotToken != NULL) && (memberRefExpr->mDotToken->GetToken() == BfToken_QuestionDot); bool isNullCondLookup = (memberRefExpr->mDotToken != NULL) && (memberRefExpr->mDotToken->GetToken() == BfToken_QuestionDot);
bool isCascade = ((memberRefExpr->mDotToken != NULL) && (memberRefExpr->mDotToken->GetToken() == BfToken_DotDot)); bool isCascade = ((memberRefExpr->mDotToken != NULL) && (memberRefExpr->mDotToken->GetToken() == BfToken_DotDot));
bool isArrowLookup = ((memberRefExpr->mDotToken != NULL) && (memberRefExpr->mDotToken->GetToken() == BfToken_Arrow));
BfIdentifierNode* nameLeft = BfNodeDynCast<BfIdentifierNode>(memberRefExpr->mTarget); BfIdentifierNode* nameLeft = BfNodeDynCast<BfIdentifierNode>(memberRefExpr->mTarget);
BfIdentifierNode* nameRight = BfIdentifierCast(memberRefExpr->mMemberName); BfIdentifierNode* nameRight = BfIdentifierCast(memberRefExpr->mMemberName);
if ((nameLeft != NULL) && (nameRight != NULL) && (!isNullCondLookup) && (!isCascade)) if ((nameLeft != NULL) && (nameRight != NULL) && (!isNullCondLookup) && (!isCascade) && (!isArrowLookup))
{ {
bool hadError = false; bool hadError = false;
LookupQualifiedName(memberRefExpr, nameLeft, nameRight, true, &hadError); LookupQualifiedName(memberRefExpr, nameLeft, nameRight, true, &hadError);
@ -20856,6 +20869,9 @@ void BfExprEvaluator::DoMemberReference(BfMemberReferenceExpression* memberRefEx
if (isNullCondLookup) if (isNullCondLookup)
thisValue = SetupNullConditional(thisValue, memberRefExpr->mDotToken); thisValue = SetupNullConditional(thisValue, memberRefExpr->mDotToken);
if ((isArrowLookup) && (thisValue))
thisValue = TryArrowLookup(thisValue, memberRefExpr->mDotToken);
mResult = LookupField(nameRefNode, thisValue, findName); mResult = LookupField(nameRefNode, thisValue, findName);
if ((!mResult) && (mPropDef == NULL)) if ((!mResult) && (mPropDef == NULL))
@ -21093,7 +21109,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
mPropDef = foundProp; mPropDef = foundProp;
if (foundProp->mIsStatic) if (foundProp->mIsStatic)
{ {
mPropTarget = BfTypedValue(curCheckType); mPropTarget = BfTypedValue(foundPropTypeInst);
} }
else else
{ {

View file

@ -508,6 +508,7 @@ public:
BfLambdaInstance* GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr, BfAllocTarget& allocTarget); BfLambdaInstance* GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr, BfAllocTarget& allocTarget);
void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor); void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic); void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
BfTypedValue TryArrowLookup(BfTypedValue typedValue, BfTokenNode* arrowToken);
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags); void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags);
BfTypedValue PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags); BfTypedValue PerformUnaryOperation_TryOperator(const BfTypedValue& inValue, BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags);
void PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags); void PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken, BfUnaryOpFlags opFlags);

View file

@ -7136,7 +7136,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
ParamFlag_None = 0, ParamFlag_None = 0,
ParamFlag_Splat = 1, ParamFlag_Splat = 1,
ParamFlag_Implicit = 2, ParamFlag_Implicit = 2,
ParamFlag_AppendIdx = 4 ParamFlag_AppendIdx = 4,
ParamFlag_Params = 8
}; };
SizedArray<BfIRValue, 8> paramVals; SizedArray<BfIRValue, 8> paramVals;
@ -7150,6 +7151,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
paramFlags = (ParamFlags)(paramFlags | ParamFlag_Splat); paramFlags = (ParamFlags)(paramFlags | ParamFlag_Splat);
if (defaultMethod->GetParamKind(paramIdx) == BfParamKind_AppendIdx) if (defaultMethod->GetParamKind(paramIdx) == BfParamKind_AppendIdx)
paramFlags = (ParamFlags)(paramFlags | ParamFlag_Implicit | ParamFlag_AppendIdx); paramFlags = (ParamFlags)(paramFlags | ParamFlag_Implicit | ParamFlag_AppendIdx);
if (defaultMethod->GetParamKind(paramIdx) == BfParamKind_Params)
paramFlags = (ParamFlags)(paramFlags | ParamFlag_Params);
BfIRValue paramNameConst = GetStringObjectValue(paramName, !mIsComptimeModule); BfIRValue paramNameConst = GetStringObjectValue(paramName, !mIsComptimeModule);

View file

@ -2556,9 +2556,12 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
mToken = BfToken_MinusEquals; mToken = BfToken_MinusEquals;
mSrcIdx++; mSrcIdx++;
} }
else if ((mCompatMode) && (mSrc[mSrcIdx] == '>')) else if (mSrc[mSrcIdx] == '>')
{ {
mToken = BfToken_Dot; if (mCompatMode)
mToken = BfToken_Dot;
else
mToken = BfToken_Arrow;
mSrcIdx++; mSrcIdx++;
} }
else else

View file

@ -2913,7 +2913,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
{ {
exprLeft = CreateIndexerExpression(exprLeft); exprLeft = CreateIndexerExpression(exprLeft);
} }
else if ((token == BfToken_Dot) || (token == BfToken_DotDot) || (token == BfToken_QuestionDot)) else if ((token == BfToken_Dot) || (token == BfToken_DotDot) || (token == BfToken_QuestionDot) || (token == BfToken_Arrow))
{ {
if ((token == BfToken_DotDot) && ((createExprFlags & CreateExprFlags_BreakOnCascade) != 0)) if ((token == BfToken_DotDot) && ((createExprFlags & CreateExprFlags_BreakOnCascade) != 0))
return exprLeft; return exprLeft;
@ -5506,7 +5506,10 @@ BfIdentifierNode* BfReducer::CompactQualifiedName(BfAstNode* leftNode)
// If the previous dotted span failed (IE: had chevrons) then don't insert qualified names in the middle of it // If the previous dotted span failed (IE: had chevrons) then don't insert qualified names in the middle of it
auto prevNodeToken = BfNodeDynCast<BfTokenNode>(prevNode); auto prevNodeToken = BfNodeDynCast<BfTokenNode>(prevNode);
if ((prevNodeToken != NULL) && ((prevNodeToken->GetToken() == BfToken_Dot) || (prevNodeToken->GetToken() == BfToken_QuestionDot))) if ((prevNodeToken != NULL) &&
((prevNodeToken->GetToken() == BfToken_Dot) ||
(prevNodeToken->GetToken() == BfToken_QuestionDot) ||
(prevNodeToken->GetToken() == BfToken_Arrow)))
return leftIdentifier; return leftIdentifier;
mVisitorPos.MoveNext(); // past . mVisitorPos.MoveNext(); // past .
@ -8120,7 +8123,7 @@ BfExpression* BfReducer::CreateIndexerExpression(BfExpression* target)
BfMemberReferenceExpression* BfReducer::CreateMemberReferenceExpression(BfAstNode* target) BfMemberReferenceExpression* BfReducer::CreateMemberReferenceExpression(BfAstNode* target)
{ {
auto tokenNode = ExpectTokenAfter(target, BfToken_Dot, BfToken_DotDot, BfToken_QuestionDot); auto tokenNode = ExpectTokenAfter(target, BfToken_Dot, BfToken_DotDot, BfToken_QuestionDot, BfToken_Arrow);
auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>(); auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
if (target != NULL) if (target != NULL)
@ -9356,7 +9359,8 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
if ((paramIdx == 0) && ( if ((paramIdx == 0) && (
(token == BfToken_In) || (token == BfToken_Out) || (token == BfToken_Ref) || (token == BfToken_Mut) || (token == BfToken_In) || (token == BfToken_Out) || (token == BfToken_Ref) || (token == BfToken_Mut) ||
(token == BfToken_Delegate) || (token == BfToken_Function) || (token == BfToken_Delegate) || (token == BfToken_Function) ||
(token == BfToken_Comptype) || (token == BfToken_Decltype) || (token == BfToken_Comptype) || (token == BfToken_Decltype) ||
(token == BfToken_AllocType) || (token == BfToken_RetType) ||
(token == BfToken_Params) || (token == BfToken_LParen) || (token == BfToken_Params) || (token == BfToken_LParen) ||
(token == BfToken_Var) || (token == BfToken_LBracket) || (token == BfToken_Var) || (token == BfToken_LBracket) ||
(token == BfToken_ReadOnly) || (token == BfToken_DotDotDot))) (token == BfToken_ReadOnly) || (token == BfToken_DotDotDot)))
@ -9413,7 +9417,8 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
BfToken token = tokenNode->GetToken(); BfToken token = tokenNode->GetToken();
if ((token == BfToken_Var) || (token == BfToken_LParen) || if ((token == BfToken_Var) || (token == BfToken_LParen) ||
(token == BfToken_Delegate) || (token == BfToken_Function) || (token == BfToken_Delegate) || (token == BfToken_Function) ||
(token == BfToken_Comptype) || (token == BfToken_Decltype) || (token == BfToken_Comptype) || (token == BfToken_Decltype) ||
(token == BfToken_AllocType) || (token == BfToken_RetType) ||
(token == BfToken_DotDotDot)) (token == BfToken_DotDotDot))
{ {
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();

View file

@ -6011,11 +6011,28 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
_Fail("paramIdx is out of range"); _Fail("paramIdx is out of range");
return false; return false;
} }
enum ParamFlags
{
ParamFlag_None = 0,
ParamFlag_Splat = 1,
ParamFlag_Implicit = 2,
ParamFlag_AppendIdx = 4,
ParamFlag_Params = 8
};
ParamFlags paramFlags = ParamFlag_None;
if (methodInstance->GetParamIsSplat(paramIdx))
paramFlags = (ParamFlags)(paramFlags | ParamFlag_Splat);
if (methodInstance->GetParamKind(paramIdx) == BfParamKind_AppendIdx)
paramFlags = (ParamFlags)(paramFlags | ParamFlag_Implicit | ParamFlag_AppendIdx);
if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params)
paramFlags = (ParamFlags)(paramFlags | ParamFlag_Params);
addr_ce stringAddr = GetString(methodInstance->GetParamName(paramIdx)); addr_ce stringAddr = GetString(methodInstance->GetParamName(paramIdx));
_FixVariables(); _FixVariables();
*(int32*)(stackPtr + 0) = methodInstance->GetParamType(paramIdx)->mTypeId; *(int32*)(stackPtr + 0) = methodInstance->GetParamType(paramIdx)->mTypeId;
*(int16*)(stackPtr + 4) = 0; // Flags *(int16*)(stackPtr + 4) = (int16)paramFlags;
CeSetAddrVal(stackPtr + 4+2, stringAddr, ptrSize); CeSetAddrVal(stackPtr + 4+2, stringAddr, ptrSize);
} }
else if (checkFunction->mFunctionKind == CeFunctionKind_Method_GetGenericArg) else if (checkFunction->mFunctionKind == CeFunctionKind_Method_GetGenericArg)

View file

@ -709,6 +709,13 @@ namespace Tests
Test.Assert(sA == 222); Test.Assert(sA == 222);
Val += 1000; Val += 1000;
Test.Assert(sA == 1222); Test.Assert(sA == 1222);
RefCounted<String> rcStr = .Create("Abc");
Test.Assert(rcStr->Length == 3);
rcStr->Clear();
rcStr.Release();
//RefCounted<StructB> rcB = .Create();
} }
struct IntStruct struct IntStruct
@ -740,8 +747,6 @@ namespace Tests
} }
} }
[Test] [Test]
public static void TestCompareWithCastOperator() public static void TestCompareWithCastOperator()
{ {