Skip to content

Commit

Permalink
Fix issue #43715
Browse files Browse the repository at this point in the history
  • Loading branch information
rdulmina committed Dec 20, 2024
1 parent e4df726 commit 3bb4433
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ public class DataflowAnalyzer extends BLangNodeVisitor {
private Map<BSymbol, Location> unusedErrorVarsDeclaredWithVar;
private Map<BSymbol, Location> unusedLocalVariables;
private final Map<BSymbol, BSymbol> symbolOwner;
private final Map<BSymbol, BSymbol> dependsOnLambda;
private final Map<BSymbol, BSymbol> invocationToDependent;
private Map<BSymbol, Set<BSymbol>> globalNodeDependsOn;
private Map<BSymbol, Set<BSymbol>> functionToDependency;
private Map<BLangOnFailClause, Map<BSymbol, InitStatus>> possibleFailureUnInitVars;
Expand All @@ -296,6 +298,8 @@ private DataflowAnalyzer(CompilerContext context) {
this.globalVariableRefAnalyzer = GlobalVariableRefAnalyzer.getInstance(context);
this.unusedLocalVariables = new HashMap<>();
this.symbolOwner = new HashMap<>();
this.dependsOnLambda = new HashMap<>();
this.invocationToDependent = new HashMap<>();
}

public static DataflowAnalyzer getInstance(CompilerContext context) {
Expand Down Expand Up @@ -355,6 +359,7 @@ public void visit(BLangPackage pkgNode) {
}
checkForUninitializedGlobalVars(pkgNode.globalVars);
pkgNode.getTestablePkgs().forEach(testablePackage -> visit((BLangPackage) testablePackage));
updateProvidersForLambdaInvocations();
this.globalVariableRefAnalyzer.analyzeAndReOrder(pkgNode, this.globalNodeDependsOn, this.symbolOwner);
this.globalVariableRefAnalyzer.populateFunctionDependencies(this.functionToDependency, pkgNode.globalVars);
pkgNode.globalVariableDependencies = globalVariableRefAnalyzer.getGlobalVariablesDependsOn();
Expand All @@ -369,6 +374,21 @@ public void visit(BLangPackage pkgNode) {
pkgNode.completedPhases.add(CompilerPhase.DATAFLOW_ANALYZE);
}

/**
* When seeing a lambda function expression, we do not add it as a provider to current dependent symbol.
* Instead, we need to add it as a provider when it is invoked. This method is used to update the providers
* for those invocations.
*/
private void updateProvidersForLambdaInvocations() {
for (Map.Entry<BSymbol, BSymbol> entry : dependsOnLambda.entrySet()) {
BSymbol dependent= entry.getKey();
BSymbol lambda = entry.getValue();
if (invocationToDependent.containsKey(dependent) && globalNodeDependsOn.containsKey(dependent)) {
globalNodeDependsOn.get(dependent).add(lambda);
}
}
}

private void addModuleInitToSortedNodeList(BLangPackage pkgNode, List<TopLevelNode> sortedListOfNodes) {
for (TopLevelNode node : pkgNode.topLevelNodes) {
if (isModuleInitFunction((BLangNode) node)) {
Expand Down Expand Up @@ -1690,6 +1710,8 @@ public void visit(BLangInvocation invocationExpr) {
BSymbol symbol = invocationExpr.symbol;
this.unusedLocalVariables.remove(symbol);

invocationToDependent.put(symbol, this.currDependentSymbolDeque.peek());

if (isFunctionOrMethodDefinedInCurrentModule(symbol.owner, env) &&
!isGlobalVarsInitialized(invocationExpr.pos, invocationExpr)) {
checkVarRef(symbol, invocationExpr.pos);
Expand Down Expand Up @@ -2131,7 +2153,9 @@ public void visit(BLangLambdaFunction bLangLambdaFunction) {
BLangFunction funcNode = bLangLambdaFunction.function;
SymbolEnv funcEnv = SymbolEnv.createFunctionEnv(funcNode, funcNode.symbol.scope, env);
visitFunctionBodyWithDynamicEnv(funcNode, funcEnv);
recordGlobalVariableReferenceRelationship(funcNode.symbol);
if (isGlobalVarSymbol(funcNode.symbol)) {
dependsOnLambda.put(this.currDependentSymbolDeque.peek(), funcNode.symbol);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public void globalDefinitionsWithCyclicReferences() {
Assert.assertTrue(diagnostics.length > 0);
BAssertUtil.validateError(resultNegativeCycleFound, 0, "illegal cyclic reference '[person, employee]'", 17, 1);
BAssertUtil.validateError(resultNegativeCycleFound, 1, "illegal cyclic reference '[dep2, dep1]'", 24, 1);
BAssertUtil.validateError(resultNegativeCycleFound, 1,
"illegal cyclic reference '[lambdaFoo, $lambda$_0, myBool]'", 26, 1);
}

@Test(description = "Test re-ordering global variable initializations to satisfy dependency order")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ Person person = {
[Employee, Person] pp2 = [employee, person];

int dep2 = dep1;

function() returns boolean lambdaFoo = function() returns boolean {
return myBool;
};

boolean myBool = lambdaFoo();

0 comments on commit 3bb4433

Please sign in to comment.