Skip to content

Commit

Permalink
fix: generation of extra statements for parameters of expression lamb…
Browse files Browse the repository at this point in the history
…das (#1137)

Closes #1136

### Summary of Changes

Extra statements that were generated for the expression of an expression
lambda were incorrectly placed outside the lambda. This broke the code
generation for parameters of expression lambdas that were used as
receivers of method calls (see the linked issue).
  • Loading branch information
lars-reimann authored May 3, 2024
1 parent 7b8ae60 commit 4add401
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -604,10 +604,12 @@ export class SafeDsPythonGenerator {
private generateExpressionLambda(node: SdsExpressionLambda, frame: GenerationInfoFrame): Generated {
const name = frame.getUniqueLambdaName(node);
const parameters = this.generateParameters(node.parameterList, frame);
const result = this.generateExpression(node.result, frame);
const lambdaFrame = frame.newScope();
const result = this.generateExpression(node.result, lambdaFrame);

const extraStatement = expandTracedToNode(node)`
def ${name}(${parameters}):
${joinToNode(lambdaFrame.getExtraStatements())}
return ${result}
`;
frame.addExtraStatement(node, extraStatement);
Expand Down Expand Up @@ -1204,8 +1206,9 @@ class GenerationInfoFrame {
insidePipeline: boolean = false,
targetPlaceholders: string[] | undefined = undefined,
disableRunnerIntegration: boolean = false,
idManager: IdManager<SdsExpression> = new IdManager(),
) {
this.idManager = new IdManager();
this.idManager = idManager;
this.importSet = importSet;
this.utilitySet = utilitySet;
this.typeVariableSet = typeVariableSet;
Expand Down Expand Up @@ -1262,6 +1265,18 @@ class GenerationInfoFrame {
getUniqueReceiverName(receiver: SdsExpression): string {
return `${RECEIVER_PREFIX}${this.idManager.assignId(receiver)}`;
}

newScope(): GenerationInfoFrame {
return new GenerationInfoFrame(
this.importSet,
this.utilitySet,
this.typeVariableSet,
this.isInsidePipeline,
this.targetPlaceholders,
this.disableRunnerIntegration,
this.idManager,
);
}
}

export interface GenerateOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Imports ----------------------------------------------------------------------

import safeds_runner
from tests.generation.python.runnerIntegration.blockLambdas import f

# Pipelines --------------------------------------------------------------------

def myPipeline():
def __gen_lambda_1(p):
__gen_receiver_0 = p
__gen_block_lambda_result_r = safeds_runner.memoized_dynamic_call(
__gen_receiver_0,
"g",
[],
{},
[]
)
return __gen_block_lambda_result_r
__gen_result = safeds_runner.memoized_static_call(
"tests.generation.python.runnerIntegration.blockLambdas.f",
f,
[__gen_lambda_1],
{},
[]
)
safeds_runner.save_placeholder('result', __gen_result)

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .gen_input import myPipeline

if __name__ == '__main__':
myPipeline()
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Related to https://github.com/Safe-DS/DSL/issues/1136

package tests.generation.python.runnerIntegration.blockLambdas

class MyClass {
@Pure
fun g() -> r: Int
}

@Pure
fun f(
callback: (p: MyClass) -> (r: Int)
) -> result: Any

pipeline myPipeline {
val result = f(
(p) {
yield r = p.g();
}
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Imports ----------------------------------------------------------------------

import safeds_runner
from tests.generation.python.runnerIntegration.expressionLambdas import f

# Pipelines --------------------------------------------------------------------

def myPipeline():
def __gen_lambda_0(p):
__gen_receiver_1 = p
return safeds_runner.memoized_dynamic_call(
__gen_receiver_1,
"g",
[],
{},
[]
)
__gen_result = safeds_runner.memoized_static_call(
"tests.generation.python.runnerIntegration.expressionLambdas.f",
f,
[__gen_lambda_0],
{},
[]
)
safeds_runner.save_placeholder('result', __gen_result)

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .gen_input import myPipeline

if __name__ == '__main__':
myPipeline()
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Related to https://github.com/Safe-DS/DSL/issues/1136

package tests.generation.python.runnerIntegration.expressionLambdas

class MyClass {
@Pure
fun g() -> r: Int
}

@Pure
fun f(
callback: (p: MyClass) -> (r: Int)
) -> result: Any

pipeline myPipeline {
val result = f(
(p) -> p.g()
);
}

0 comments on commit 4add401

Please sign in to comment.