Skip to content

Commit 25c8707

Browse files
authored
feat: compute types of lambdas that are passed as arguments (#604)
Closes partially #541 ### Summary of Changes * Compute the type of parameters of lambdas that are passed as arguments. * Compute the type of lambdas that are passed as arguments.
1 parent a13e5b5 commit 25c8707

File tree

18 files changed

+45
-32
lines changed

18 files changed

+45
-32
lines changed

src/language/helpers/safe-ds-node-mapper.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import { argumentsOrEmpty, parametersOrEmpty, typeArgumentsOrEmpty, typeParamete
2323
import { isNamedArgument, isNamedTypeArgument } from './checks.js';
2424

2525
export class SafeDsNodeMapper {
26-
private readonly typeComputer: SafeDsTypeComputer;
26+
private readonly typeComputer: () => SafeDsTypeComputer;
2727

2828
constructor(services: SafeDsServices) {
29-
this.typeComputer = new SafeDsTypeComputer(services);
29+
this.typeComputer = () => services.types.TypeComputer;
3030
}
3131

3232
/**
@@ -36,7 +36,7 @@ export class SafeDsNodeMapper {
3636
if (isSdsAnnotationCall(node)) {
3737
return node.annotation?.ref;
3838
} else if (isSdsCall(node)) {
39-
const receiverType = this.typeComputer.computeType(node.receiver);
39+
const receiverType = this.typeComputer().computeType(node.receiver);
4040
if (receiverType instanceof CallableType) {
4141
return receiverType.sdsCallable;
4242
} else if (receiverType instanceof StaticType) {

src/language/typing/safe-ds-type-computer.ts

+16-13
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,19 @@ import {
7979
resultsOrEmpty,
8080
typeArgumentsOrEmpty,
8181
} from '../helpers/shortcuts.js';
82+
import { SafeDsNodeMapper } from '../helpers/safe-ds-node-mapper.js';
8283

8384
export class SafeDsTypeComputer {
84-
readonly astNodeLocator: AstNodeLocator;
85-
readonly coreClasses: SafeDsCoreClasses;
85+
private readonly astNodeLocator: AstNodeLocator;
86+
private readonly coreClasses: SafeDsCoreClasses;
87+
private readonly nodeMapper: SafeDsNodeMapper;
8688

8789
readonly typeCache: WorkspaceCache<string, Type>;
8890

8991
constructor(readonly services: SafeDsServices) {
9092
this.astNodeLocator = services.workspace.AstNodeLocator;
9193
this.coreClasses = services.builtins.CoreClasses;
94+
this.nodeMapper = services.helpers.NodeMapper;
9295

9396
this.typeCache = new WorkspaceCache(services.shared);
9497
}
@@ -214,20 +217,20 @@ export class SafeDsTypeComputer {
214217
const containerOfLambda = containingCallable.$container;
215218

216219
// Lambda passed as argument
217-
/* c8 ignore start */
218220
if (isSdsArgument(containerOfLambda)) {
219-
// val containerType = when (val container = callable.eContainer()) {
220-
// is SdsArgument -> container.parameterOrNull()?.inferType(context)
221-
// }
222-
//
223-
// return when (containerType) {
224-
// is CallableType -> containerType.parameters.getOrElse(thisIndex) { Any(context) }
225-
// else -> Any(context)
226-
// }
221+
const parameter = this.nodeMapper.argumentToParameterOrUndefined(containerOfLambda);
222+
if (!parameter) {
223+
return UnknownType;
224+
}
227225

228-
return NotImplementedType;
226+
const parameterType = this.computeType(parameter?.type);
227+
if (!(parameterType instanceof CallableType)) {
228+
return UnknownType;
229+
}
230+
231+
const parameterPosition = node.$containerIndex ?? -1;
232+
return parameterType.getParameterTypeByPosition(parameterPosition) ?? UnknownType;
229233
}
230-
/* c8 ignore stop */
231234

232235
// Yielded lambda
233236
else if (isSdsAssignment(containerOfLambda)) {

tests/resources/typing/declarations/parameters/of block lambdas/that are isolated.sdstest tests/resources/typing/declarations/parameters/of block lambdas/that are isolated/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofBlockLambdas
1+
package tests.typing.declarations.parameters.ofBlockLambdas.thatAreIsolated
22

33
segment mySegment() {
44
// $TEST$ serialization $Unknown

tests/resources/typing/declarations/parameters/of block lambdas/skip-that are passed as argument.sdstest tests/resources/typing/declarations/parameters/of block lambdas/that are passed as arguments/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofBlockLambdas
1+
package tests.typing.declarations.parameters.ofBlockLambdas.thatArePassedAsArguments
22

33
// $TEST$ equivalence_class parameterType1
44
fun higherOrderFunction1(param: (a: »String«) -> ())

tests/resources/typing/declarations/parameters/of block lambdas/that are yielded.sdstest tests/resources/typing/declarations/parameters/of block lambdas/that are yielded/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofBlockLambdas
1+
package tests.typing.declarations.parameters.ofBlockLambdas.thatAreYielded
22

33
segment mySegment() -> (
44
// $TEST$ equivalence_class parameterType2

tests/resources/typing/declarations/parameters/of block lambdas/with manifest types.sdstest tests/resources/typing/declarations/parameters/of block lambdas/with manifest types/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofBlockLambdas
1+
package tests.typing.declarations.parameters.ofBlockLambdas.withManifestTypes
22

33
segment mySegment() {
44
// $TEST$ equivalence_class parameterType3

tests/resources/typing/declarations/parameters/of expression lambdas/that are isolated.sdstest tests/resources/typing/declarations/parameters/of expression lambdas/that are isolated/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofExpressionLambdas
1+
package tests.typing.declarations.parameters.ofExpressionLambdas.thatAreIsolated
22

33
segment mySegment() {
44
// $TEST$ serialization $Unknown

tests/resources/typing/declarations/parameters/of expression lambdas/skip-that are passed as argument.sdstest tests/resources/typing/declarations/parameters/of expression lambdas/that are passed as arguments/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofExpressionLambdas
1+
package tests.typing.declarations.parameters.ofExpressionLambdas.thatArePassedAsArguments
22

33
// $TEST$ equivalence_class parameterType1
44
fun higherOrderFunction1(param: (a: »String«) -> r: String)

tests/resources/typing/declarations/parameters/of expression lambdas/that are yielded.sdstest tests/resources/typing/declarations/parameters/of expression lambdas/that are yielded/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofExpressionLambdas
1+
package tests.typing.declarations.parameters.ofExpressionLambdas.thatAreYielded
22

33
segment mySegment() -> (
44
// $TEST$ equivalence_class parameterType2

tests/resources/typing/declarations/parameters/of expression lambdas/with manifest types.sdstest tests/resources/typing/declarations/parameters/of expression lambdas/with manifest types/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.declarations.parameters.ofExpressionLambdas
1+
package tests.typing.declarations.parameters.ofExpressionLambdas.withManifestTypes
22

33
segment mySegment() {
44
// $TEST$ equivalence_class parameterType3

tests/resources/typing/expressions/block lambdas/that are isolated.sdstest tests/resources/typing/expressions/block lambdas/that are isolated/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.expressions.blockLambdas
1+
package tests.typing.expressions.blockLambdas.thatAreIsolated
22

33
segment mySegment() {
44
// $TEST$ serialization (p: $Unknown) -> (r: Int, s: $Unknown)

tests/resources/typing/expressions/block lambdas/skip-that are passed as argument.sdstest tests/resources/typing/expressions/block lambdas/that are passed as arguments/main.sdstest

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
package tests.typing.expressions.blockLambdas
1+
package tests.typing.expressions.blockLambdas.thatArePassedAsArguments
22

33
fun higherOrderFunction1(param: (p: String) -> (r: Int, s: String))
44
fun higherOrderFunction2(param: () -> ())
55
fun normalFunction(param: Int)
6+
fun parameterlessFunction()
67

78
segment mySegment() {
89
// $TEST$ serialization (p: String) -> (r: Int, s: String)
@@ -37,4 +38,9 @@ segment mySegment() {
3738
normalFunction(param = »(p) {
3839
yield r, yield s = 1;
3940
}«);
41+
42+
// $TEST$ serialization (p: $Unknown) -> (r: Int, s: $Unknown)
43+
parameterlessFunction(»(p) {
44+
yield r, yield s = 1;
45+
}«);
4046
}

tests/resources/typing/expressions/block lambdas/that are yielded.sdstest tests/resources/typing/expressions/block lambdas/that are yielded/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.expressions.blockLambdas
1+
package tests.typing.expressions.blockLambdas.thatAreYielded
22

33
segment mySegment() -> (
44
r: (p: String) -> (r: Int, s: String),

tests/resources/typing/expressions/block lambdas/with manifest types.sdstest tests/resources/typing/expressions/block lambdas/with manifest types/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.expressions.blockLambdas
1+
package tests.typing.expressions.blockLambdas.withManifestTypes
22

33
segment mySegment() {
44
// $TEST$ serialization (p: Int) -> (r: Int, s: String)

tests/resources/typing/expressions/expression lambdas/that are isolated.sdstest tests/resources/typing/expressions/expression lambdas/that are isolated/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.expressions.expressionLambdas
1+
package tests.typing.expressions.expressionLambdas.thatAreIsolated
22

33
segment mySegment() {
44
// $TEST$ serialization (p: $Unknown) -> (result: Int)

tests/resources/typing/expressions/expression lambdas/skip-that are passed as argument.sdstest tests/resources/typing/expressions/expression lambdas/that are passed as arguments/main.sdstest

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
package tests.typing.expressions.expressionLambdas
1+
package tests.typing.expressions.expressionLambdas.thatArePassedAsArguments
22

33
fun higherOrderFunction1(param: (p: String) -> (r: Int))
44
fun higherOrderFunction2(param: () -> ())
55
fun normalFunction(param: Int)
6+
fun parameterlessFunction()
67

78
segment mySegment() {
89
// $TEST$ serialization (p: String) -> (result: Int)
@@ -22,4 +23,7 @@ segment mySegment() {
2223

2324
// $TEST$ serialization (p: $Unknown) -> (result: Int)
2425
normalFunction(param = »(p) -> 1«);
26+
27+
// $TEST$ serialization (p: $Unknown) -> (result: Int)
28+
parameterlessFunction(»(p) -> 1«);
2529
}

tests/resources/typing/expressions/expression lambdas/that are yielded.sdstest tests/resources/typing/expressions/expression lambdas/that are yielded/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.expressions.expressionLambdas
1+
package tests.typing.expressions.expressionLambdas.thatAreYielded
22

33
segment mySegment() -> (
44
r: (p: String) -> (),

tests/resources/typing/expressions/expression lambdas/with manifest types.sdstest tests/resources/typing/expressions/expression lambdas/with manifest types/main.sdstest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tests.typing.expressions.expressionLambdas
1+
package tests.typing.expressions.expressionLambdas.withManifestTypes
22

33
segment mySegment() {
44
// $TEST$ serialization (p: Int) -> (result: Int)

0 commit comments

Comments
 (0)