Skip to content

Commit

Permalink
simplify the logic for creating invoke for synthesized ctor
Browse files Browse the repository at this point in the history
Separate the logic of _invokeExprForSynthesizedCtor from
_readAggregateValueFromInitializerList.

Because we don't really need to read and coerce the values recursively
from the initializer list when we go this path. After we form a invoke
expression to synthesized ctor, the ResolveInvoke logic will help us to
coerce the arguments.
  • Loading branch information
kaizhangNV committed Oct 2, 2024
1 parent c759f4d commit 04c9a9f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 95 deletions.
146 changes: 64 additions & 82 deletions source/slang/slang-check-conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ namespace Slang
Type* toType,
Expr** outToExpr,
InitializerListExpr* fromInitializerListExpr,
UInt &ioInitArgIndex,
bool useLegacyMode)
UInt &ioInitArgIndex)
{
// First, we will check if we have run out of arguments
// on the initializer list.
Expand Down Expand Up @@ -161,8 +160,7 @@ namespace Slang
toType,
outToExpr,
fromInitializerListExpr,
ioInitArgIndex,
useLegacyMode);
ioInitArgIndex);
}

DeclRefType* findBaseStructType(ASTBuilder* astBuilder, DeclRef<StructDecl> structTypeDeclRef)
Expand Down Expand Up @@ -277,36 +275,27 @@ namespace Slang

bool SemanticsVisitor::_invokeExprForSynthesizedCtor(
Type* toType,
StructDecl* structDecl,
InitializerListExpr* fromInitializerListExpr,
UInt &ioArgIndex,
Expr** outExpr)
{
auto synthesizedConstructor = _getSynthesizedConstructor(structDecl);
SLANG_ASSERT(synthesizedConstructor);

List<Expr*> coercedArgs;

for(auto param : getParameters(getASTBuilder(), synthesizedConstructor))
StructDecl* structDecl = nullptr;
if(auto toDeclRefType = as<DeclRefType>(toType))
{
Expr* coercedArg = nullptr;
bool argResult = _readValueFromInitializerList(
getType(m_astBuilder, param),
&coercedArg,
fromInitializerListExpr,
ioArgIndex);

// No point in trying further if any argument fails
if(!argResult)
return false;

if( coercedArg )
auto toTypeDeclRef = toDeclRefType->getDeclRef();
if(auto toStructDeclRef = toTypeDeclRef.as<StructDecl>())
{
coercedArgs.add(coercedArg);
structDecl = toStructDeclRef.getDecl();
}
}

auto ctorInvokeExpr = _prepareCtorInvokeExpr(toType, fromInitializerListExpr->loc, coercedArgs);
if (!structDecl || isFromStdLib(structDecl))
return false;

auto synthesizedConstructor = _getSynthesizedConstructor(structDecl);
SLANG_ASSERT(synthesizedConstructor);

List<Expr*> coercedArgs;
auto ctorInvokeExpr = _prepareCtorInvokeExpr(toType, fromInitializerListExpr->loc, fromInitializerListExpr->args);
if (ctorInvokeExpr)
{
// The reason we need to check the coercion again is that the ResolveInvoke() could still find us
Expand Down Expand Up @@ -343,8 +332,7 @@ namespace Slang
Type* inToType,
Expr** outToExpr,
InitializerListExpr* fromInitializerListExpr,
UInt &ioArgIndex,
bool useLegacyMode)
UInt &ioArgIndex)
{
auto toType = inToType;
UInt argCount = fromInitializerListExpr->args.getCount();
Expand Down Expand Up @@ -565,62 +553,50 @@ namespace Slang
auto toTypeDeclRef = toDeclRefType->getDeclRef();
if(auto toStructDeclRef = toTypeDeclRef.as<StructDecl>())
{
// TODO: create a function '_createCtorInvokeExpr()'
// We must have a synthesized constructor here there are only two cases that we don't synthesized constructor:
// 1. It is a stdlib struct.
// 2. It is a struct that has user defined constructor. (In this case, we should have already handled it in _coerceInitializerList)
if (!isFromStdLib(toStructDeclRef.getDecl()) && !useLegacyMode)
{
return _invokeExprForSynthesizedCtor(inToType, toStructDeclRef.getDecl(), fromInitializerListExpr, ioArgIndex, outToExpr);
}
else
// Trying to initialize a `struct` type given an initializer list.
//
// Before we iterate over the fields, we want to check if this struct
// inherits from another `struct` type. If so, we want to read
// an initializer for that base type first.
//
if (auto baseStructType = findBaseStructType(m_astBuilder, toStructDeclRef))
{
// Trying to initialize a `struct` type given an initializer list.
//
// Before we iterate over the fields, we want to check if this struct
// inherits from another `struct` type. If so, we want to read
// an initializer for that base type first.
//
if (auto baseStructType = findBaseStructType(m_astBuilder, toStructDeclRef))
Expr* coercedArg = nullptr;
bool argResult = _readValueFromInitializerList(
baseStructType,
outToExpr ? &coercedArg : nullptr,
fromInitializerListExpr,
ioArgIndex);

// No point in trying further if any argument fails
if (!argResult)
return false;

if (coercedArg)
{
Expr* coercedArg = nullptr;
bool argResult = _readValueFromInitializerList(
baseStructType,
outToExpr ? &coercedArg : nullptr,
fromInitializerListExpr,
ioArgIndex);

// No point in trying further if any argument fails
if (!argResult)
return false;

if (coercedArg)
{
coercedArgs.add(coercedArg);
}
coercedArgs.add(coercedArg);
}
}

// We will go through the fields in order and try to match them
// up with initializer arguments.
//
for(auto fieldDeclRef : getMembersOfType<VarDecl>(m_astBuilder, toStructDeclRef, MemberFilterStyle::Instance))
// We will go through the fields in order and try to match them
// up with initializer arguments.
//
for(auto fieldDeclRef : getMembersOfType<VarDecl>(m_astBuilder, toStructDeclRef, MemberFilterStyle::Instance))
{
Expr* coercedArg = nullptr;
bool argResult = _readValueFromInitializerList(
getType(m_astBuilder, fieldDeclRef),
outToExpr ? &coercedArg : nullptr,
fromInitializerListExpr,
ioArgIndex);

// No point in trying further if any argument fails
if(!argResult)
return false;

if( coercedArg )
{
Expr* coercedArg = nullptr;
bool argResult = _readValueFromInitializerList(
getType(m_astBuilder, fieldDeclRef),
outToExpr ? &coercedArg : nullptr,
fromInitializerListExpr,
ioArgIndex,
true);

// No point in trying further if any argument fails
if(!argResult)
return false;

if( coercedArg )
{
coercedArgs.add(coercedArg);
}
coercedArgs.add(coercedArg);
}
}
}
Expand Down Expand Up @@ -704,12 +680,18 @@ namespace Slang
return true;
}

// try to invoke the synthesized constructor if it exists
if (_invokeExprForSynthesizedCtor(toType, fromInitializerListExpr, outToExpr))
{
// TODO: check if it's C-style initializer list
// if it's not, return error.
// if it is, return, fall-back to legacy logic
}

// We will fall back to the legacy logic of initialize list.
if(!_readAggregateValueFromInitializerList(toType, outToExpr, fromInitializerListExpr, argIndex))
{
bool useLegacyMode = true;
if(!_readAggregateValueFromInitializerList(toType, outToExpr, fromInitializerListExpr, argIndex, useLegacyMode))
return false;
return false;
}

if(argIndex != argCount)
Expand Down
16 changes: 3 additions & 13 deletions source/slang/slang-check-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1499,8 +1499,7 @@ namespace Slang
Type* toType,
Expr** outToExpr,
InitializerListExpr* fromInitializerListExpr,
UInt &ioInitArgIndex,
bool useLegacyMode = false);
UInt &ioInitArgIndex);

/// Read an aggregate value from an initializer list expression.
///
Expand All @@ -1525,8 +1524,7 @@ namespace Slang
Type* inToType,
Expr** outToExpr,
InitializerListExpr* fromInitializerListExpr,
UInt &ioArgIndex,
bool useLegacyMode = false);
UInt &ioArgIndex);

/// Coerce an initializer-list expression to a specific type.
///
Expand Down Expand Up @@ -2761,18 +2759,10 @@ namespace Slang
CompletionSuggestions::ScopeKind scopeKind, LookupResult const& lookupResult);

bool _invokeExprForExplicitCtor(Type* toType, InitializerListExpr* fromInitializerListExpr, Expr** outExpr);
bool _invokeExprForSynthesizedCtor(
Type* toType,
StructDecl* structDecl,
InitializerListExpr* fromInitializerListExpr,
UInt &ioArgIndex,
Expr** outExpr);

bool _invokeExprForSynthesizedCtor(Type* toType, InitializerListExpr* fromInitializerListExpr, Expr** outExpr);
Expr* _prepareCtorInvokeExpr(Type* toType, const SourceLoc& loc, const List<Expr*>& coercedArgs);

bool _hasExplicitConstructor(StructDecl* structDecl);
ConstructorDecl* _getSynthesizedConstructor(StructDecl* structDecl);

};


Expand Down

0 comments on commit 04c9a9f

Please sign in to comment.