Skip to content

Commit e66f736

Browse files
committed
Support for default parameters on modules
1 parent 5ac7448 commit e66f736

File tree

5 files changed

+164
-36
lines changed

5 files changed

+164
-36
lines changed

source/modules/soul_core/compiler/soul_AST.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,8 @@ struct AST
909909

910910
virtual bool isResolved() const = 0;
911911

912-
virtual Type getResultType() const { SOUL_ASSERT_FALSE; return {}; }
913-
virtual Type resolveAsType() const { SOUL_ASSERT_FALSE; return {}; }
912+
virtual Type getResultType() const { context.throwError (Errors::expectedType()); }
913+
virtual Type resolveAsType() const { context.throwError (Errors::expectedType()); }
914914
virtual pool_ptr<ProcessorBase> getAsProcessor() const { return {}; }
915915
virtual pool_ptr<Namespace> getAsNamespace() const { return {}; }
916916
virtual pool_ptr<EndpointDeclaration> getAsEndpoint() const { return {}; }
@@ -1454,10 +1454,11 @@ struct AST
14541454
{
14551455
}
14561456

1457-
bool isResolved() const { return targetProcessor != nullptr; }
1457+
bool isResolved() const { return resolvedProcessor != nullptr; }
14581458

14591459
Identifier name;
1460-
pool_ptr<ProcessorBase> targetProcessor;
1460+
pool_ptr<Expression> targetProcessor;
1461+
pool_ptr<ProcessorBase> resolvedProcessor;
14611462
};
14621463

14631464
//==============================================================================

source/modules/soul_core/compiler/soul_ASTUtilities.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,42 +194,43 @@ struct ASTUtilities
194194
static std::string getSpecialisationSignature (const ParamList& params, const ArgList& args)
195195
{
196196
std::stringstream key;
197-
SOUL_ASSERT (args.size() == params.size());
198197

199-
for (size_t i = 0; i < args.size(); ++i)
198+
for (size_t i = 0; i < params.size(); ++i)
200199
{
201-
auto& arg = args[i].get();
202200
auto& param = params[i];
203201

204202
if (i > 0)
205203
key << ',';
206204

207205
if (auto u = cast<AST::UsingDeclaration> (param))
208206
{
209-
if (arg.resolveAsType().isStruct())
210-
key << getSignatureString (arg.resolveAsType().getStruct().get());
207+
auto targetType = (i < args.size()) ? args[i]->resolveAsType() : u->targetType->resolveAsType();
208+
209+
if (targetType.isStruct())
210+
key << getSignatureString (targetType.getStruct().get());
211211
else
212-
key << arg.resolveAsType().getShortIdentifierDescription();
212+
key << targetType.getShortIdentifierDescription();
213213

214214
continue;
215215
}
216216

217217
if (auto v = cast<AST::VariableDeclaration> (param))
218218
{
219-
auto& value = arg.getAsConstant()->value;
219+
auto& value = (i < args.size()) ? args[i]->getAsConstant()->value : v->initialValue->getAsConstant()->value;
220220
key << std::string (static_cast<const char*> (value.getPackedData()), value.getPackedDataSize());
221221
continue;
222222
}
223223

224224
if (auto v = cast<AST::NamespaceAliasDeclaration> (param))
225225
{
226-
key << getSignatureString (v->resolvedNamespace.get());
226+
auto ns = (i < args.size()) ? cast<AST::NamespaceRef> (args[i])->ns : v->resolvedNamespace;
227+
key << getSignatureString (ns.get());
227228
continue;
228229
}
229230

230231
if (auto v = cast<AST::ProcessorAliasDeclaration> (param))
231232
{
232-
key << getSignatureString (v->targetProcessor.get());
233+
key << getSignatureString (v->resolvedProcessor.get());
233234
continue;
234235
}
235236

source/modules/soul_core/compiler/soul_ASTVisitor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ struct ASTVisitor
316316
visitObject (c.source);
317317
}
318318

319-
virtual void visit (AST::ProcessorAliasDeclaration&)
319+
virtual void visit (AST::ProcessorAliasDeclaration& a)
320320
{
321+
visitObjectIfNotNull (a.targetProcessor);
321322
}
322323

323324
virtual void visit (AST::EndpointDeclaration& e)
@@ -796,6 +797,7 @@ struct RewritingASTVisitor
796797

797798
virtual AST::ProcessorAliasDeclaration& visit (AST::ProcessorAliasDeclaration& a)
798799
{
800+
replaceExpression (a.targetProcessor);
799801
return a;
800802
}
801803

source/modules/soul_core/compiler/soul_Parser.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,29 +483,50 @@ struct StructuralParser : public Tokeniser<Keyword::Matcher,
483483

484484
auto context = getContext();
485485
auto name = parseIdentifier();
486-
module->addSpecialisationParameter (allocate<AST::UsingDeclaration> (context, name, nullptr));
486+
487+
auto& usingDeclaration = allocate<AST::UsingDeclaration> (context, name, nullptr);
488+
489+
if (matchIf (Operator::assign))
490+
usingDeclaration.targetType = parseType (ParseTypeContext::variableType);
491+
492+
module->addSpecialisationParameter (usingDeclaration);
487493
}
488494
else if (matchIf (Keyword::processor))
489495
{
490496
if (! module->isGraph())
491497
throwError (Errors::processorSpecialisationNotAllowed());
492498

493499
auto context = getContext();
494-
module->addSpecialisationParameter (allocate<AST::ProcessorAliasDeclaration> (context, parseIdentifier()));
500+
auto& processorAliasDeclaration = allocate<AST::ProcessorAliasDeclaration> (context, parseIdentifier());
501+
502+
if (matchIf (Operator::assign))
503+
processorAliasDeclaration.targetProcessor = parseType (ParseTypeContext::nameOrType);
504+
505+
module->addSpecialisationParameter (processorAliasDeclaration);
506+
495507
}
496508
else if (matchIf (Keyword::namespace_))
497509
{
498510
if (! module->isNamespace())
499511
throwError (Errors::namespaceSpecialisationNotAllowed());
500512

501513
auto context = getContext();
502-
module->addSpecialisationParameter (allocate<AST::NamespaceAliasDeclaration> (context, parseIdentifier()));
514+
auto& namespaceAliasDeclaration = allocate<AST::NamespaceAliasDeclaration> (context, parseIdentifier());
515+
516+
if (matchIf (Operator::assign))
517+
namespaceAliasDeclaration.targetNamespace = parseType (ParseTypeContext::nameOrType);
518+
519+
module->addSpecialisationParameter (namespaceAliasDeclaration);
503520
}
504521
else
505522
{
506523
giveErrorOnExternalKeyword();
507524
auto& parameterType = parseType (ParseTypeContext::processorParameter);
508525
auto& parameterVariable = allocate<AST::VariableDeclaration> (getContext(), parameterType, nullptr, true);
526+
527+
if (matchIf (Operator::assign))
528+
parameterVariable.initialValue = parseExpression();
529+
509530
parameterVariable.name = parseIdentifier();
510531
module->addSpecialisationParameter (parameterVariable);
511532
}

source/modules/soul_core/compiler/soul_ResolutionPass.h

Lines changed: 122 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,15 @@ struct ResolutionPass final
506506
return allocator.allocate<AST::ProcessorInstanceRef> (qi.context, *p);
507507

508508
if (auto pa = cast<AST::ProcessorAliasDeclaration> (item))
509+
{
509510
if (pa->isResolved())
510-
return allocator.allocate<AST::ProcessorRef> (qi.context, *pa->targetProcessor);
511+
{
512+
if (currentConnectionEndpoint != nullptr)
513+
return getOrCreateImplicitProcessorInstance (qi.context, *pa->resolvedProcessor, {});
514+
515+
return allocator.allocate<AST::ProcessorRef> (qi.context, *pa->resolvedProcessor);
516+
}
517+
}
511518

512519
if (auto e = cast<AST::EndpointDeclaration> (item))
513520
return ASTUtilities::createEndpointRef (allocator, qi.context, *e);
@@ -1638,6 +1645,68 @@ struct ResolutionPass final
16381645
using ArgList = decltype(AST::CommaSeparatedList::items);
16391646
using ParamList = decltype(AST::ModuleBase::specialisationParams);
16401647

1648+
bool validateSpecialisationParam (AST::ASTObject& param) const
1649+
{
1650+
if (auto u = cast<AST::UsingDeclaration> (param))
1651+
{
1652+
if (u->targetType == nullptr)
1653+
return true;
1654+
1655+
if (AST::isResolvedAsType (*u->targetType))
1656+
return true;
1657+
1658+
if (! ignoreErrors)
1659+
u->targetType->context.throwError (Errors::expectedType());
1660+
1661+
return false;
1662+
}
1663+
else if (auto pa = cast<AST::ProcessorAliasDeclaration> (param))
1664+
{
1665+
if (pa->targetProcessor == nullptr)
1666+
return true;
1667+
1668+
pa->resolvedProcessor = pa->targetProcessor->getAsProcessor();
1669+
1670+
if (pa->resolvedProcessor != nullptr)
1671+
return true;
1672+
1673+
if (! ignoreErrors)
1674+
pa->targetProcessor->context.throwError (Errors::expectedProcessorName());
1675+
1676+
return false;
1677+
}
1678+
else if (auto v = cast<AST::VariableDeclaration> (param))
1679+
{
1680+
if (v->initialValue == nullptr)
1681+
return true;
1682+
1683+
if (AST::isResolvedAsValue (*v->initialValue))
1684+
return true;
1685+
1686+
if (! ignoreErrors)
1687+
v->initialValue->context.throwError (Errors::expectedValue());
1688+
1689+
return false;
1690+
}
1691+
else if (auto n = cast<AST::NamespaceAliasDeclaration> (param))
1692+
{
1693+
if (n->targetNamespace == nullptr)
1694+
return true;
1695+
1696+
n->resolvedNamespace = n->targetNamespace->getAsNamespace();
1697+
1698+
if (n->resolvedNamespace != nullptr)
1699+
return true;
1700+
1701+
if (! ignoreErrors)
1702+
n->targetNamespace->context.throwError (Errors::expectedNamespaceName());
1703+
1704+
return false;
1705+
}
1706+
1707+
return false;
1708+
}
1709+
16411710
bool canResolveSpecialisationArg (AST::Expression& arg, AST::ASTObject& param) const
16421711
{
16431712
if (auto u = cast<AST::UsingDeclaration> (param))
@@ -1650,8 +1719,7 @@ struct ResolutionPass final
16501719

16511720
return false;
16521721
}
1653-
1654-
if (auto pa = cast<AST::ProcessorAliasDeclaration> (param))
1722+
else if (auto pa = cast<AST::ProcessorAliasDeclaration> (param))
16551723
{
16561724
if (auto prf = cast<AST::ProcessorInstanceRef> (arg))
16571725
return prf->processorInstance.specialisationArgs == nullptr
@@ -1665,8 +1733,7 @@ struct ResolutionPass final
16651733

16661734
return false;
16671735
}
1668-
1669-
if (auto v = cast<AST::VariableDeclaration> (param))
1736+
else if (auto v = cast<AST::VariableDeclaration> (param))
16701737
{
16711738
if (AST::isResolvedAsValue (arg))
16721739
{
@@ -1679,8 +1746,7 @@ struct ResolutionPass final
16791746

16801747
return false;
16811748
}
1682-
1683-
if (auto n = cast<AST::NamespaceAliasDeclaration> (param))
1749+
else if (auto n = cast<AST::NamespaceAliasDeclaration> (param))
16841750
{
16851751
if (arg.isResolved())
16861752
{
@@ -1697,11 +1763,49 @@ struct ResolutionPass final
16971763
return false;
16981764
}
16991765

1766+
bool validateSpecialisationArgs (const ArgList& args, const ParamList& params) const
1767+
{
1768+
for (size_t i = 0; i < params.size(); ++i)
1769+
if (! validateSpecialisationParam (params[i]))
1770+
return false;
1771+
1772+
if (args.size() == params.size())
1773+
return true;
1774+
1775+
if (args.size() > params.size())
1776+
return false;
1777+
1778+
for (auto i = args.size(); i < params.size(); i++)
1779+
{
1780+
if (auto x = cast<AST::UsingDeclaration> (params[i]))
1781+
{
1782+
if (x->targetType == nullptr)
1783+
return false;
1784+
}
1785+
else if (auto n = cast<AST::NamespaceAliasDeclaration> (params[i]))
1786+
{
1787+
if (n->resolvedNamespace == nullptr)
1788+
return false;
1789+
}
1790+
else if (auto p = cast<AST::ProcessorAliasDeclaration> (params[i]))
1791+
{
1792+
if (p->resolvedProcessor == nullptr)
1793+
return false;
1794+
}
1795+
else
1796+
{
1797+
return false;
1798+
}
1799+
}
1800+
1801+
return true;
1802+
}
1803+
17001804
bool canResolveAllSpecialisationArgs (const ArgList& args, const ParamList& params) const
17011805
{
1702-
SOUL_ASSERT (args.size() == params.size());
1806+
SOUL_ASSERT (args.size() <= params.size());
17031807

1704-
for (size_t i = 0; i < params.size(); ++i)
1808+
for (size_t i = 0; i < args.size(); ++i)
17051809
if (! canResolveSpecialisationArg (args[i].get(), params[i]))
17061810
return false;
17071811

@@ -1720,7 +1824,7 @@ struct ResolutionPass final
17201824
if (auto pa = cast<AST::ProcessorAliasDeclaration> (param))
17211825
{
17221826
auto pr = arg.getAsProcessor();
1723-
pa->targetProcessor = *pr;
1827+
pa->resolvedProcessor = *pr;
17241828
return;
17251829
}
17261830

@@ -1746,10 +1850,10 @@ struct ResolutionPass final
17461850

17471851
static void resolveAllSpecialisationArgs (const ArgList& args, ParamList& params)
17481852
{
1749-
SOUL_ASSERT (args.size() == params.size());
1853+
SOUL_ASSERT (args.size() <= params.size());
17501854

1751-
for (size_t i = 0; i < params.size(); ++i)
1752-
resolveSpecialisationArg (args[i].get(), params[i]);
1855+
for (size_t i = 0; i < args.size(); ++i)
1856+
resolveSpecialisationArg (args[i], params[i]);
17531857

17541858
params.clear();
17551859
}
@@ -1778,8 +1882,8 @@ struct ResolutionPass final
17781882
auto numArgs = specialisationArgs.size();
17791883
auto target = pool_ref<AST::ProcessorBase> (*p);
17801884

1781-
if (target->specialisationParams.size() != numArgs)
1782-
instance.context.throwError (Errors::wrongNumArgsForProcessor (target->getFullyQualifiedPath()));
1885+
if (! validateSpecialisationArgs (specialisationArgs, target->specialisationParams))
1886+
instance.context.throwError (Errors::wrongNumArgsForNamespace (target->getFullyQualifiedPath()));
17831887

17841888
auto& graph = *cast<AST::Graph> (instance.getParentScope()->findProcessor());
17851889
SanityCheckPass::RecursiveGraphDetector::check (graph);
@@ -1858,11 +1962,10 @@ struct ResolutionPass final
18581962
return instance;
18591963

18601964
auto specialisationArgs = AST::CommaSeparatedList::getAsExpressionList (instance.specialisationArgs);
1861-
auto numArgs = specialisationArgs.size();
18621965

18631966
if (auto target = instance.targetNamespace->getAsNamespace())
18641967
{
1865-
if (target->specialisationParams.size() != numArgs)
1968+
if (! validateSpecialisationArgs (specialisationArgs, target->specialisationParams))
18661969
instance.context.throwError (Errors::wrongNumArgsForNamespace (target->getFullyQualifiedPath()));
18671970

18681971
if (canResolveAllSpecialisationArgs (specialisationArgs, target->specialisationParams))
@@ -1884,10 +1987,10 @@ struct ResolutionPass final
18841987

18851988
AST::Namespace& getOrAddNamespaceSpecialisation (AST::Namespace& namespaceToClone, const ArgList& specialisationArgs)
18861989
{
1887-
SOUL_ASSERT (namespaceToClone.specialisationParams.size() == specialisationArgs.size());
1990+
SOUL_ASSERT (specialisationArgs.size() <= namespaceToClone.specialisationParams.size());
18881991

18891992
// No parameters, just use the existing namespace
1890-
if (specialisationArgs.empty())
1993+
if (namespaceToClone.specialisationParams.empty())
18911994
return namespaceToClone;
18921995

18931996
auto instanceKey = ASTUtilities::getSpecialisationSignature (namespaceToClone.specialisationParams, specialisationArgs);

0 commit comments

Comments
 (0)