From 82052688a0b965c968283a1e6be4a912159fe405 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 19:28:30 +0100 Subject: [PATCH 1/9] feat: check type of yields --- .../language/validation/safe-ds-validator.ts | 3 ++- .../src/language/validation/types.ts | 25 +++++++++++++++++++ .../tests/language/validation/creator.ts | 4 +-- .../other/imports/main with issues.sdstest | 4 +-- .../skip-old/schemaEffectArguments.sdstest | 22 ---------------- .../validation/skip-old/yields.sdstest | 13 ---------- .../types/checking/yields/main.sdstest | 16 ++++++++++++ 7 files changed, 47 insertions(+), 40 deletions(-) delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/schemaEffectArguments.sdstest delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/yields.sdstest create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index ed7705395..2f47a3b35 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -49,6 +49,7 @@ import { namedTypeMustSetAllTypeParameters, parameterMustHaveTypeHint, resultMustHaveTypeHint, + yieldTypeMustMatchResultType, } from './types.js'; import { moduleDeclarationsMustMatchFileKind, @@ -299,7 +300,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { unionTypeShouldNotHaveDuplicateTypes(services), unionTypeShouldNotHaveASingularTypeArgument, ], - SdsYield: [yieldMustNotBeUsedInPipeline], + SdsYield: [yieldMustNotBeUsedInPipeline, yieldTypeMustMatchResultType(services)], }; registry.register(checks); }; diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index 974359d1a..40d97a25e 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -13,6 +13,7 @@ import { SdsNamedType, SdsParameter, SdsResult, + SdsYield, } from '../generated/ast.js'; import { getTypeArguments, getTypeParameters } from '../helpers/nodeProperties.js'; import { SafeDsServices } from '../safe-ds-module.js'; @@ -20,6 +21,7 @@ import { pluralize } from '../../helpers/stringUtils.js'; import { isEmpty } from '../../helpers/collectionUtils.js'; export const CODE_TYPE_CALLABLE_RECEIVER = 'type/callable-receiver'; +export const CODE_TYPE_YIELD = 'type/yield'; export const CODE_TYPE_MISSING_TYPE_ARGUMENTS = 'type/missing-type-arguments'; export const CODE_TYPE_MISSING_TYPE_HINT = 'type/missing-type-hint'; @@ -60,6 +62,29 @@ export const callReceiverMustBeCallable = (services: SafeDsServices) => { }; }; +export const yieldTypeMustMatchResultType = (services: SafeDsServices) => { + const typeChecker = services.types.TypeChecker; + const typeComputer = services.types.TypeComputer; + + return (node: SdsYield, accept: ValidationAcceptor) => { + const result = node.result?.ref; + if (!result) { + return; + } + + const yieldType = typeComputer.computeType(node); + const resultType = typeComputer.computeType(result); + + if (!typeChecker.isAssignableTo(yieldType, resultType)) { + accept('error', `A value of type '${yieldType}' cannot be assigned to a result of type '${resultType}'.`, { + node, + property: 'result', + code: CODE_TYPE_YIELD, + }); + } + }; +}; + // ----------------------------------------------------------------------------- // Missing type arguments // ----------------------------------------------------------------------------- diff --git a/packages/safe-ds-lang/tests/language/validation/creator.ts b/packages/safe-ds-lang/tests/language/validation/creator.ts index 2122ca890..6640d9d54 100644 --- a/packages/safe-ds-lang/tests/language/validation/creator.ts +++ b/packages/safe-ds-lang/tests/language/validation/creator.ts @@ -6,7 +6,7 @@ import fs from 'fs'; import { findTestChecks } from '../../helpers/testChecks.js'; import { getSyntaxErrors, SyntaxErrorsInCodeError } from '../../helpers/diagnostics.js'; import { EmptyFileSystem, URI } from 'langium'; -import { createSafeDsServices } from '../../../src/language/safe-ds-module.js'; +import { createSafeDsServices } from '../../../src/language/index.js'; import { Range } from 'vscode-languageserver'; import { TestDescription, TestDescriptionError } from '../../helpers/testDescription.js'; @@ -40,7 +40,7 @@ const createValidationTest = async (parentDirectory: URI, uris: URI[]): Promise< } for (const check of checksResult.value) { - const regex = /\s*(?no\s+)?(?\S+)\s*(?:(?r)?"(?[^"]*)")?/gu; + const regex = /\s*(?no\s+)?(?\S+)\s*(?:(?r)?"(?.*)")?/gu; const match = regex.exec(check.comment); // Overall comment is invalid diff --git a/packages/safe-ds-lang/tests/resources/validation/other/imports/main with issues.sdstest b/packages/safe-ds-lang/tests/resources/validation/other/imports/main with issues.sdstest index bb2154698..85cdcf696 100644 --- a/packages/safe-ds-lang/tests/resources/validation/other/imports/main with issues.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/other/imports/main with issues.sdstest @@ -2,9 +2,9 @@ package tests.other.imports // $TEST$ error "The package 'tests.other.imports.missing' does not exist." from »tests.other.imports.missing« import * -// $TEST$ error ""The package 'tests.other.imports.missing' does not exist." +// $TEST$ error "The package 'tests.other.imports.missing' does not exist." from »tests.other.imports.missing« import C -// $TEST$ error ""The package 'tests.other.imports.missing' does not exist." +// $TEST$ error "The package 'tests.other.imports.missing' does not exist." from »tests.other.imports.missing« import C as D // $TEST$ warning "The package 'tests.other.imports.empty' is empty." diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/schemaEffectArguments.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/schemaEffectArguments.sdstest deleted file mode 100644 index c325a2ef5..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/schemaEffectArguments.sdstest +++ /dev/null @@ -1,22 +0,0 @@ -package tests.validation.typeChecking.schemaEffectArguments - -predicate schemaEffects (){ - - /* $ReadSchema ---------------------------------------------------------------------------------------------------*/ - // $TEST$ error "An argument of type 'Boolean' cannot be assigned to a parameter of type 'String'." - $readSchema(»false«), - - // $TEST$ no error "An argument of type 'String' cannot be assigned to a parameter of type 'String'." - $readSchema(»"datasetNameStr"«), - - /* $CheckColumn --------------------------------------------------------------------------------------------------*/ - // $TEST$ error "An argument of type 'Boolean' cannot be assigned to a parameter of type '::$SchemaType'." - // $TEST$ error "An argument of type 'Int' cannot be assigned to a parameter of type 'vararg'." - // $TEST$ no error "An argument of type 'safeds.lang.String' cannot be assigned to a parameter of type 'safeds.lang.String'." - $checkColumn(»false«, »0«, »"columnNameStr2"«), - - // $TEST$ no error "An argument of type '::$SchemaType' cannot be assigned to a parameter of type '::$SchemaType'." - // $TEST$ no error "An argument of type 'String' cannot be assigned to a parameter of type 'vararg'." - // $TEST$ no error "An argument of type 'String' cannot be assigned to a parameter of type 'String'." - $checkColumn(»::ASchema«, »"columnNameStr1"«, »"columnNameStr2"«) -} diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/yields.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/yields.sdstest deleted file mode 100644 index 3cfeb4c78..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/yields.sdstest +++ /dev/null @@ -1,13 +0,0 @@ -package tests.validation.typeChecking.yields - -step myStep1() -> result: Int { - - // $TEST$ no error "A value of type 'Int' cannot be assigned to a result of type 'Int'." - yield result = »1«; -} - -step myStep2() -> result: Int { - - // $TEST$ error "A value of type 'String' cannot be assigned to a result of type 'Int'." - yield result = »""«; -} diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest new file mode 100644 index 000000000..f0eef5442 --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest @@ -0,0 +1,16 @@ +package tests.validation.types.checking.yields + +segment mySegment1() -> result: Int { + // $TEST$ no error r"A value of type .* cannot be assigned to a result of type .*\." + yield »result« = 1; +} + +segment mySegment2() -> result: Int { + // $TEST$ error "A value of type 'literal<"">' cannot be assigned to a result of type 'Int'." + yield »result« = ""; +} + +segment mySegment3() { + // $TEST$ no error r"A value of type .* cannot be assigned to a result of type .*\." + yield »result« = 1; +} From 1a965b53b75ec134e5ff98a81fbcadf1e44d0556 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 19:36:30 +0100 Subject: [PATCH 2/9] feat: check type of default values --- .../language/validation/safe-ds-validator.ts | 2 ++ .../src/language/validation/types.ts | 28 +++++++++++++++++++ .../validation/skip-old/defaultValues.sdstest | 19 ------------- .../checking/default values/main.sdstest | 19 +++++++++++++ 4 files changed, 49 insertions(+), 19 deletions(-) delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/defaultValues.sdstest create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index 2f47a3b35..b5c7277c8 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -47,6 +47,7 @@ import { attributeMustHaveTypeHint, callReceiverMustBeCallable, namedTypeMustSetAllTypeParameters, + parameterDefaultValueTypeMustMatchParameterType, parameterMustHaveTypeHint, resultMustHaveTypeHint, yieldTypeMustMatchResultType, @@ -267,6 +268,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsParameter: [ constantParameterMustHaveConstantDefaultValue(services), parameterMustHaveTypeHint, + parameterDefaultValueTypeMustMatchParameterType(services), requiredParameterMustNotBeDeprecated(services), requiredParameterMustNotBeExpert(services), ], diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index 40d97a25e..5bc6e34a4 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -21,6 +21,7 @@ import { pluralize } from '../../helpers/stringUtils.js'; import { isEmpty } from '../../helpers/collectionUtils.js'; export const CODE_TYPE_CALLABLE_RECEIVER = 'type/callable-receiver'; +export const CODE_TYPE_DEFAULT_VALUE = 'type/default-value'; export const CODE_TYPE_YIELD = 'type/yield'; export const CODE_TYPE_MISSING_TYPE_ARGUMENTS = 'type/missing-type-arguments'; export const CODE_TYPE_MISSING_TYPE_HINT = 'type/missing-type-hint'; @@ -62,6 +63,33 @@ export const callReceiverMustBeCallable = (services: SafeDsServices) => { }; }; +export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDsServices) => { + const typeChecker = services.types.TypeChecker; + const typeComputer = services.types.TypeComputer; + + return (node: SdsParameter, accept: ValidationAcceptor) => { + const defaultValue = node.defaultValue; + if (!defaultValue) { + return; + } + + const defaultValueType = typeComputer.computeType(defaultValue); + const parameterType = typeComputer.computeType(node); + + if (!typeChecker.isAssignableTo(defaultValueType, parameterType)) { + accept( + 'error', + `A default value of type '${defaultValueType}' cannot be assigned to a parameter of type '${parameterType}'.`, + { + node, + property: 'defaultValue', + code: CODE_TYPE_DEFAULT_VALUE, + }, + ); + } + }; +}; + export const yieldTypeMustMatchResultType = (services: SafeDsServices) => { const typeChecker = services.types.TypeChecker; const typeComputer = services.types.TypeComputer; diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/defaultValues.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/defaultValues.sdstest deleted file mode 100644 index f1ce05cde..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/defaultValues.sdstest +++ /dev/null @@ -1,19 +0,0 @@ -package tests.validation.typeChecking.defaultValues - -fun myFun( - // $TEST$ no error "An default value of type 'Int' cannot be assigned to a parameter of type 'Int'." - param1: Int = »1«, - - // $TEST$ error "A default value of type 'String' cannot be assigned to a parameter of type 'Int'." - param2: Int = »""«, -) - -fun myOtherFun(callback: (a: Int) -> ()) - -step myStep() { - // $TEST$ no error "An default value of type 'Int' cannot be assigned to a parameter of type 'Int'." - myOtherFun((a = »1«) {}); - - // $TEST$ error "A default value of type 'String' cannot be assigned to a parameter of type 'Int'." - myOtherFun((a = »""«) {}); -} diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest new file mode 100644 index 000000000..9cee4b5c4 --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest @@ -0,0 +1,19 @@ +package tests.validation.types.checking.defaultValues + +fun myFun( + // $TEST$ no error r"A default value of type .* cannot be assigned to a parameter of type .*\." + param1: Int = »1«, + + // $TEST$ error "A default value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + param2: Int = »""«, +) + +fun myOtherFun(callback: (a: Int) -> ()) + +segment mySegment() { + // $TEST$ no error r"A default value of type .* cannot be assigned to a parameter of type .*\." + myOtherFun((a = »1«) {}); + + // $TEST$ error "A default value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + myOtherFun((a = »""«) {}); +} From 984e756094ecef71ca8d87403e49144478666e11 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 19:46:13 +0100 Subject: [PATCH 3/9] feat: check type of arguments --- .../language/validation/safe-ds-validator.ts | 2 ++ .../src/language/validation/types.ts | 36 ++++++++++++++++--- .../types/checking/arguments/main.sdstest | 20 +++++++++++ .../types/checking/yields/main.sdstest | 2 +- 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index b5c7277c8..77ed053ef 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -44,6 +44,7 @@ import { yieldMustNotBeUsedInPipeline, } from './other/statements/assignments.js'; import { + argumentTypeMustMatchParameterType, attributeMustHaveTypeHint, callReceiverMustBeCallable, namedTypeMustSetAllTypeParameters, @@ -184,6 +185,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsArgument: [ argumentCorrespondingParameterShouldNotBeDeprecated(services), argumentCorrespondingParameterShouldNotBeExperimental(services), + argumentTypeMustMatchParameterType(services), ], SdsArgumentList: [ argumentListMustNotHavePositionalArgumentsAfterNamedArguments, diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index 5bc6e34a4..ace89d032 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -8,6 +8,7 @@ import { isSdsPipeline, isSdsReference, isSdsSchema, + SdsArgument, SdsAttribute, SdsCall, SdsNamedType, @@ -21,8 +22,7 @@ import { pluralize } from '../../helpers/stringUtils.js'; import { isEmpty } from '../../helpers/collectionUtils.js'; export const CODE_TYPE_CALLABLE_RECEIVER = 'type/callable-receiver'; -export const CODE_TYPE_DEFAULT_VALUE = 'type/default-value'; -export const CODE_TYPE_YIELD = 'type/yield'; +export const CODE_TYPE_MISMATCH = 'type/mismatch'; export const CODE_TYPE_MISSING_TYPE_ARGUMENTS = 'type/missing-type-arguments'; export const CODE_TYPE_MISSING_TYPE_HINT = 'type/missing-type-hint'; @@ -30,6 +30,34 @@ export const CODE_TYPE_MISSING_TYPE_HINT = 'type/missing-type-hint'; // Type checking // ----------------------------------------------------------------------------- +export const argumentTypeMustMatchParameterType = (services: SafeDsServices) => { + const nodeMapper = services.helpers.NodeMapper; + const typeChecker = services.types.TypeChecker; + const typeComputer = services.types.TypeComputer; + + return (node: SdsArgument, accept: ValidationAcceptor) => { + const parameter = nodeMapper.argumentToParameter(node); + if (!parameter) { + return; + } + + const argumentType = typeComputer.computeType(node); + const parameterType = typeComputer.computeType(parameter); + + if (!typeChecker.isAssignableTo(argumentType, parameterType)) { + accept( + 'error', + `A value of type '${argumentType}' cannot be assigned to a parameter of type '${parameterType}'.`, + { + node, + property: 'value', + code: CODE_TYPE_MISMATCH, + }, + ); + } + }; +}; + export const callReceiverMustBeCallable = (services: SafeDsServices) => { const nodeMapper = services.helpers.NodeMapper; @@ -83,7 +111,7 @@ export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDs { node, property: 'defaultValue', - code: CODE_TYPE_DEFAULT_VALUE, + code: CODE_TYPE_MISMATCH, }, ); } @@ -107,7 +135,7 @@ export const yieldTypeMustMatchResultType = (services: SafeDsServices) => { accept('error', `A value of type '${yieldType}' cannot be assigned to a result of type '${resultType}'.`, { node, property: 'result', - code: CODE_TYPE_YIELD, + code: CODE_TYPE_MISMATCH, }); } }; diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest new file mode 100644 index 000000000..f7a098e7f --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest @@ -0,0 +1,20 @@ +package tests.validation.types.checking.arguments + +fun f(p: Int) + +segment mySegment() { + // $TEST$ no error r"A value of type .* cannot be assigned to a parameter of type .*\." + f(»1«); + + // $TEST$ no error r"A value of type .* cannot be assigned to a parameter of type .*\." + f(p = »1«); + + // $TEST$ error "A value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + f(»""«); + + // $TEST$ error "A value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + f(p = »""«); + + // $TEST$ no error r"A value of type .* cannot be assigned to a parameter of type .*\." + f(unresolved = »1«); +} diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest index f0eef5442..9d1ace530 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest @@ -12,5 +12,5 @@ segment mySegment2() -> result: Int { segment mySegment3() { // $TEST$ no error r"A value of type .* cannot be assigned to a result of type .*\." - yield »result« = 1; + yield »unresolved« = 1; } From 591986670f96e7fb6c84f787933a07866d32a4f5 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 20:00:49 +0100 Subject: [PATCH 4/9] feat: check type of receiver of indexed access --- .../language/validation/safe-ds-validator.ts | 3 +- .../src/language/validation/types.ts | 20 ++ .../validation/skip-old/arguments.sdstest | 336 ------------------ .../indexed access receiver/main.sdstest | 12 + 4 files changed, 34 insertions(+), 337 deletions(-) delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/arguments.sdstest create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index 77ed053ef..70d569eb2 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -47,6 +47,7 @@ import { argumentTypeMustMatchParameterType, attributeMustHaveTypeHint, callReceiverMustBeCallable, + indexedAccessReceiverMustBeListOrMap, namedTypeMustSetAllTypeParameters, parameterDefaultValueTypeMustMatchParameterType, parameterMustHaveTypeHint, @@ -230,7 +231,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { ], SdsImport: [importPackageMustExist(services), importPackageShouldNotBeEmpty(services)], SdsImportedDeclaration: [importedDeclarationAliasShouldDifferFromDeclarationName], - SdsIndexedAccess: [indexedAccessesShouldBeUsedWithCaution], + SdsIndexedAccess: [indexedAccessReceiverMustBeListOrMap(services), indexedAccessesShouldBeUsedWithCaution], SdsInfixOperation: [divisionDivisorMustNotBeZero(services), elvisOperatorShouldBeNeeded(services)], SdsLambda: [ lambdaMustBeAssignedToTypedParameter(services), diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index ace89d032..01ef75a9d 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -11,6 +11,7 @@ import { SdsArgument, SdsAttribute, SdsCall, + SdsIndexedAccess, SdsNamedType, SdsParameter, SdsResult, @@ -91,6 +92,25 @@ export const callReceiverMustBeCallable = (services: SafeDsServices) => { }; }; +export const indexedAccessReceiverMustBeListOrMap = (services: SafeDsServices) => { + const coreTypes = services.types.CoreTypes; + const typeComputer = services.types.TypeComputer; + + return (node: SdsIndexedAccess, accept: ValidationAcceptor): void => { + const receiverType = typeComputer.computeType(node.receiver); + if (receiverType !== coreTypes.List && receiverType !== coreTypes.Map) { + accept( + 'error', + `The receiver of an indexed access must be of type 'List' or 'Map' but was of type '${receiverType}'.`, + { + node: node.receiver, + code: CODE_TYPE_MISMATCH, + }, + ); + } + }; +}; + export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDsServices) => { const typeChecker = services.types.TypeChecker; const typeComputer = services.types.TypeComputer; diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/arguments.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/arguments.sdstest deleted file mode 100644 index 75895a631..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/arguments.sdstest +++ /dev/null @@ -1,336 +0,0 @@ -package tests.validation.typeChecking.arguments - -step myStep(vararg variadicParam: Int) { - - // $TEST$ no error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»f2«); - // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»B()«); - // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(callableType = »C()«); - // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»maybeC()«); - // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»someVariantOfMyEnum2()«); - // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»MyEnum1.Variant1«); - // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»aOrC()«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type '(Int) -> (Int)'." - f1(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f1(unresolved = »1«); - - // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'C'." - f2(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'C'." - f2(»f2«); - // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'C'." - f2(»B()«); - // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'C'." - f2(classType = »C()«); - // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'C'." - f2(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'C'." - f2(»maybeC()«); - // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'C'." - f2(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'C'." - f2(»someVariantOfMyEnum2()«); - // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'C'." - f2(»MyEnum1.Variant1«); - // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'C'." - f2(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'C'." - f2(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'C'." - f2(»aOrC()«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'C'." - f2(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'C'." - f2(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'C'." - f2(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f2(unresolved = »1«); - - // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»f2«); - // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»B()«); - // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type 'MyEnum1'." - f3(enumType = »C()«); - // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»maybeC()«); - // $TEST$ no error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»someVariantOfMyEnum2()«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»MyEnum1.Variant1«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»aOrC()«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'MyEnum1'." - f3(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f3(unresolved = »1«); - - // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»f2«); - // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»B()«); - // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(enumVariantType = »C()«); - // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»maybeC()«); - // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»someVariantOfMyEnum2()«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»MyEnum1.Variant1«); - // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»aOrC()«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'MyEnum1.Variant1'." - f4(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f4(unresolved = »1«); - - // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'union'." - f5(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'union'." - f5(»f2«); - // $TEST$ no error "An argument of type 'B' cannot be assigned to a parameter of type 'union'." - f5(»B()«); - // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'union'." - f5(unionType = »C()«); - // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'union'." - f5(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'union'." - f5(»maybeC()«); - // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'union'." - f5(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'union'." - f5(»someVariantOfMyEnum2()«); - // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'union'." - f5(»MyEnum1.Variant1«); - // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'union'." - f5(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'union'." - f5(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'union'." - f5(»aOrC()«); - // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'union'." - f5(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'union'." - f5(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'union'." - f5(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f5(unresolved = »1«); - - // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type '$Unresolved'." - f6(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type '$Unresolved'." - f6(»f2«); - // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type '$Unresolved'." - f6(»B()«); - // $TEST$ error "An argument of type 'C' cannot be assigned to a parameter of type '$Unresolved'." - f6(unresolvedType = »C()«); - // $TEST$ error "An argument of type 'D' cannot be assigned to a parameter of type '$Unresolved'." - f6(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type '$Unresolved'." - f6(»maybeC()«); - // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type '$Unresolved'." - f6(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type '$Unresolved'." - f6(»someVariantOfMyEnum2()«); - // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type '$Unresolved'." - f6(»MyEnum1.Variant1«); - // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type '$Unresolved'." - f6(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type '$Unresolved'." - f6(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '$Unresolved'." - f6(»aOrC()«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type '$Unresolved'." - f6(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type '$Unresolved'." - f6(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type '$Unresolved'." - f6(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f6(unresolved = »1«); - - // $TEST$ error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'vararg'." - f7(»intToInt«); - // $TEST$ error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'vararg'." - f7(»f2«); - // $TEST$ error "An argument of type 'B' cannot be assigned to a parameter of type 'vararg'." - f7(»B()«); - // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'vararg'." - f7(unresolvedType = »C()«); - // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'vararg'." - f7(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'vararg'." - f7(»maybeC()«); - // $TEST$ error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'vararg'." - f7(»someVariantOfMyEnum1()«); - // $TEST$ error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'vararg'." - f7(»someVariantOfMyEnum2()«); - // $TEST$ error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'vararg'." - f7(»MyEnum1.Variant1«); - // $TEST$ error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'vararg'." - f7(»MyEnum1.Variant2«); - // $TEST$ error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'vararg'." - f7(»MyEnum2.Variant1«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'vararg'." - f7(»aOrC()«); - // $TEST$ error "An argument of type 'union' cannot be assigned to a parameter of type 'vararg'." - f7(»bOrC()«); - // $TEST$ error "An argument of type 'vararg' cannot be assigned to a parameter of type 'vararg'." - f7(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'vararg'." - f7(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f7(unresolved = »1«); - - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f8(»(vararg a: Int) {}«); - - // $TEST$ no error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'Any'." - f9(»intToInt«); - // $TEST$ no error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'Any'." - f9(»f2«); - // $TEST$ no error "An argument of type 'B' cannot be assigned to a parameter of type 'Any'." - f9(»B()«); - // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'Any'." - f9(callableType = »C()«); - // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'Any'." - f9(»D()«); - // $TEST$ error "An argument of type 'C?' cannot be assigned to a parameter of type 'Any'." - f9(»maybeC()«); - // $TEST$ no error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'Any'." - f9(»someVariantOfMyEnum1()«); - // $TEST$ no error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'Any'." - f9(»someVariantOfMyEnum2()«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'Any'." - f9(»MyEnum1.Variant1«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'Any'." - f9(»MyEnum1.Variant2«); - // $TEST$ no error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'Any'." - f9(»MyEnum2.Variant1«); - // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any'." - f9(»aOrC()«); - // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any'." - f9(»bOrC()«); - // $TEST$ no error "An argument of type 'vararg' cannot be assigned to a parameter of type 'Any'." - f9(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'Any'." - f9(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f9(unresolved = »1«); - - // $TEST$ no error "An argument of type '(Int) -> (Int)' cannot be assigned to a parameter of type 'Any?'." - f10(»intToInt«); - // $TEST$ no error "An argument of type '(C) -> ()' cannot be assigned to a parameter of type 'Any?'." - f10(»f2«); - // $TEST$ no error "An argument of type 'B' cannot be assigned to a parameter of type 'Any?'." - f10(»B()«); - // $TEST$ no error "An argument of type 'C' cannot be assigned to a parameter of type 'Any?'." - f10(callableType = »C()«); - // $TEST$ no error "An argument of type 'D' cannot be assigned to a parameter of type 'Any?'." - f10(»D()«); - // $TEST$ no error "An argument of type 'C?' cannot be assigned to a parameter of type 'Any?'." - f10(»maybeC()«); - // $TEST$ no error "An argument of type 'MyEnum1' cannot be assigned to a parameter of type 'Any?'." - f10(»someVariantOfMyEnum1()«); - // $TEST$ no error "An argument of type 'MyEnum2' cannot be assigned to a parameter of type 'Any?'." - f10(»someVariantOfMyEnum2()«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant1' cannot be assigned to a parameter of type 'Any?'." - f10(»MyEnum1.Variant1«); - // $TEST$ no error "An argument of type 'MyEnum1.Variant2' cannot be assigned to a parameter of type 'Any?'." - f10(»MyEnum1.Variant2«); - // $TEST$ no error "An argument of type 'MyEnum2.Variant1' cannot be assigned to a parameter of type 'Any?'." - f10(»MyEnum2.Variant1«); - // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any?'." - f10(»aOrC()«); - // $TEST$ no error "An argument of type 'union' cannot be assigned to a parameter of type 'Any?'." - f10(»bOrC()«); - // $TEST$ no error "An argument of type 'vararg' cannot be assigned to a parameter of type 'Any?'." - f10(»variadicParam«); - // $TEST$ no error "An argument of type '$Unresolved' cannot be assigned to a parameter of type 'Any?'." - f10(»unresolved«); - // $TEST$ no error r"An argument of type '[^']*' cannot be assigned to a parameter of type '[^']*'." - f10(unresolved = »1«); -} - -fun f1(callableType: (a: Int) -> (r: Int)) -fun f2(classType: C) -fun f3(enumType: MyEnum1) -fun f4(enumVariantType: MyEnum1.Variant1) -fun f5(unionType: union) -fun f6(unresolvedType: Unresolved) -fun f7(vararg variadicType: C) -fun f8(callableType: (vararg a: Int) -> ()) -fun f9(any: Any) -fun f10(anyOrNull: Any?) - -class A() -class B() -class C() -class D() sub C - -enum MyEnum1 { - Variant1 - Variant2 -} -enum MyEnum2 { - Variant1 - Variant2 -} - -fun maybeC() -> instanceOrNull: C? -fun aOrC() -> instance: union -fun bOrC() -> instance: union -fun someVariantOfMyEnum1() -> variant: MyEnum1 -fun someVariantOfMyEnum2() -> variant: MyEnum2 -fun intToInt(a: Int) -> (r: Int) diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest new file mode 100644 index 000000000..9799a562b --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest @@ -0,0 +1,12 @@ +package tests.validation.types.checking.indexedAccessReceiver + +pipeline myPipeline { + // $TEST$ no error r"The receiver of an indexed access must be of type 'List' or 'Map' but was of type .*\." + »[1]«[0]; + + // $TEST$ no error r"The receiver of an indexed access must be of type 'List' or 'Map' but was of type .*\." + »{0: 1}«[0]; + + // $TEST$ error "The receiver of an indexed access must be of type 'List' or 'Map' but was of type 'literal<1>'." + »1«[0]; +} From 907c7b16e67fdf6531aa46ebf79348ee225009d5 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 20:12:37 +0100 Subject: [PATCH 5/9] feat: check type of index of indexed access on lists --- .../language/validation/safe-ds-validator.ts | 7 +++++- .../src/language/validation/types.ts | 24 +++++++++++++++++++ .../indexed access on list/main.sdstest | 12 ++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index 70d569eb2..df875e287 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -47,6 +47,7 @@ import { argumentTypeMustMatchParameterType, attributeMustHaveTypeHint, callReceiverMustBeCallable, + indexedAccessIndexMustHaveCorrectType, indexedAccessReceiverMustBeListOrMap, namedTypeMustSetAllTypeParameters, parameterDefaultValueTypeMustMatchParameterType, @@ -231,7 +232,11 @@ export const registerValidationChecks = function (services: SafeDsServices) { ], SdsImport: [importPackageMustExist(services), importPackageShouldNotBeEmpty(services)], SdsImportedDeclaration: [importedDeclarationAliasShouldDifferFromDeclarationName], - SdsIndexedAccess: [indexedAccessReceiverMustBeListOrMap(services), indexedAccessesShouldBeUsedWithCaution], + SdsIndexedAccess: [ + indexedAccessIndexMustHaveCorrectType(services), + indexedAccessReceiverMustBeListOrMap(services), + indexedAccessesShouldBeUsedWithCaution, + ], SdsInfixOperation: [divisionDivisorMustNotBeZero(services), elvisOperatorShouldBeNeeded(services)], SdsLambda: [ lambdaMustBeAssignedToTypedParameter(services), diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index 01ef75a9d..9a7665c0a 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -111,6 +111,30 @@ export const indexedAccessReceiverMustBeListOrMap = (services: SafeDsServices) = }; }; +export const indexedAccessIndexMustHaveCorrectType = (services: SafeDsServices) => { + const coreTypes = services.types.CoreTypes; + const typeChecker = services.types.TypeChecker; + const typeComputer = services.types.TypeComputer; + + return (node: SdsIndexedAccess, accept: ValidationAcceptor): void => { + const receiverType = typeComputer.computeType(node.receiver); + if (receiverType === coreTypes.List) { + const indexType = typeComputer.computeType(node.index); + if (!typeChecker.isAssignableTo(indexType, coreTypes.Int)) { + accept( + 'error', + `The index of an indexed access on a list must be of type 'Int' but was of type '${indexType}'.`, + { + node, + property: 'index', + code: CODE_TYPE_MISMATCH, + }, + ); + } + } + }; +}; + export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDsServices) => { const typeChecker = services.types.TypeChecker; const typeComputer = services.types.TypeComputer; diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest new file mode 100644 index 000000000..8bb882026 --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest @@ -0,0 +1,12 @@ +package tests.validation.types.checking.indexedAccessOnList + +pipeline myPipeline { + // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." + [1][»0«]; + + // $TEST$ error "The index of an indexed access on a list must be of type 'Int' but was of type 'literal<"">'." + [0][»""«]; + + // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." + {"": ""}[»""«]; +} From f2623723a4d70dc2556d8e35ed877ea85d1faa81 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 20:47:30 +0100 Subject: [PATCH 6/9] feat: check type of operands of prefix operations --- .../language/validation/safe-ds-validator.ts | 2 + .../src/language/validation/types.ts | 46 ++++++++++++++++++- .../skip-old/indexedAccesses.sdstest | 39 ---------------- .../skip-old/prefixOperations.sdstest | 38 --------------- .../indexed access on list/main.sdstest | 3 ++ .../indexed access receiver/main.sdstest | 3 ++ .../checking/prefix operations/main.sdstest | 20 ++++++++ 7 files changed, 72 insertions(+), 79 deletions(-) delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/indexedAccesses.sdstest delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/prefixOperations.sdstest create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index df875e287..bb3c89d0a 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -52,6 +52,7 @@ import { namedTypeMustSetAllTypeParameters, parameterDefaultValueTypeMustMatchParameterType, parameterMustHaveTypeHint, + prefixOperationOperandMustHaveCorrectType, resultMustHaveTypeHint, yieldTypeMustMatchResultType, } from './types.js'; @@ -283,6 +284,7 @@ export const registerValidationChecks = function (services: SafeDsServices) { SdsParameterList: [parameterListMustNotHaveRequiredParametersAfterOptionalParameters], SdsPipeline: [pipelineMustContainUniqueNames], SdsPlaceholder: [placeholdersMustNotBeAnAlias, placeholderShouldBeUsed(services)], + SdsPrefixOperation: [prefixOperationOperandMustHaveCorrectType(services)], SdsReference: [ referenceMustNotBeFunctionPointer, referenceMustNotBeStaticClassOrEnumReference, diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index 9a7665c0a..cd2cd662a 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -14,6 +14,7 @@ import { SdsIndexedAccess, SdsNamedType, SdsParameter, + SdsPrefixOperation, SdsResult, SdsYield, } from '../generated/ast.js'; @@ -101,7 +102,7 @@ export const indexedAccessReceiverMustBeListOrMap = (services: SafeDsServices) = if (receiverType !== coreTypes.List && receiverType !== coreTypes.Map) { accept( 'error', - `The receiver of an indexed access must be of type 'List' or 'Map' but was of type '${receiverType}'.`, + `The receiver of an indexed access must be of type '${coreTypes.List}' or '${coreTypes.Map}' but was of type '${receiverType}'.`, { node: node.receiver, code: CODE_TYPE_MISMATCH, @@ -123,7 +124,7 @@ export const indexedAccessIndexMustHaveCorrectType = (services: SafeDsServices) if (!typeChecker.isAssignableTo(indexType, coreTypes.Int)) { accept( 'error', - `The index of an indexed access on a list must be of type 'Int' but was of type '${indexType}'.`, + `The index of an indexed access on a list must be of type '${coreTypes.Int}' but was of type '${indexType}'.`, { node, property: 'index', @@ -162,6 +163,47 @@ export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDs }; }; +export const prefixOperationOperandMustHaveCorrectType = (services: SafeDsServices) => { + const coreTypes = services.types.CoreTypes; + const typeChecker = services.types.TypeChecker; + const typeComputer = services.types.TypeComputer; + + return (node: SdsPrefixOperation, accept: ValidationAcceptor): void => { + const operandType = typeComputer.computeType(node.operand); + switch (node.operator) { + case 'not': + if (!typeChecker.isAssignableTo(operandType, coreTypes.Boolean)) { + accept( + 'error', + `The operand of a logical negation must be of type '${coreTypes.Boolean}' but was of type '${operandType}'.`, + { + node, + property: 'operand', + code: CODE_TYPE_MISMATCH, + }, + ); + } + return; + case '-': + if ( + !typeChecker.isAssignableTo(operandType, coreTypes.Float) && + !typeChecker.isAssignableTo(operandType, coreTypes.Int) + ) { + accept( + 'error', + `The operand of an arithmetic negation must be of type '${coreTypes.Float}' or '${coreTypes.Int}' but was of type '${operandType}'.`, + { + node, + property: 'operand', + code: CODE_TYPE_MISMATCH, + }, + ); + } + return; + } + }; +}; + export const yieldTypeMustMatchResultType = (services: SafeDsServices) => { const typeChecker = services.types.TypeChecker; const typeComputer = services.types.TypeComputer; diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/indexedAccesses.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/indexedAccesses.sdstest deleted file mode 100644 index c741d5379..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/indexedAccesses.sdstest +++ /dev/null @@ -1,39 +0,0 @@ -package tests.validation.typeChecking.indexedAccesses - -step f(a: Int, vararg b: Int) { - // $TEST$ error "The receiver of an indexed access must refer to a variadic parameter." - »a«[0]; - - // $TEST$ no error "The receiver of an indexed access must refer to a variadic parameter." - »b«[0]; - - // $TEST$ no error "The receiver of an indexed access must refer to a variadic parameter." - »unresolved«[0]; - - // $TEST$ no error "The receiver of an indexed access must refer to a variadic parameter." - »C.unresolved«[0]; - - // $TEST$ no error "The index of an indexed access must be an instance of the class 'Int'." - b[»0«]; - - // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." - b[»""«]; - - // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." - b[»g«]; - - // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." - b[»h()«]; - - // $TEST$ error "The index of an indexed access must be an instance of the class 'Int'." - b[»b«]; - - // $TEST$ no error "The index of an indexed access must be an instance of the class 'Int'." - b[»unresolved«]; - - // $TEST$ no error "The index of an indexed access must be an instance of the class 'Int'." - b[»C.unresolved«]; -} - -fun g() -fun h() -> index: Int? diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/prefixOperations.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/prefixOperations.sdstest deleted file mode 100644 index d2c43af31..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/prefixOperations.sdstest +++ /dev/null @@ -1,38 +0,0 @@ -package tests.validation.typeChecking.prefixOperations - -step f(vararg a: Int) { - - // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »true«; - // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »false«; - // $TEST$ error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »i()«; - // $TEST$ error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »0«; - // $TEST$ error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »a«; - // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »unresolved«; - // $TEST$ no error "The operand of a logical negation must be an instance of the class 'Boolean'." - not »C.unresolved«; - - // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»0.0«; - // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»0«; - // $TEST$ error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»h()«; - // $TEST$ error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»""«; - // $TEST$ error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»a«; - // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»unresolved«; - // $TEST$ no error "The operand of an arithmetic negation must be an instance of the class 'Float' or the class 'Int'." - -»C.unresolved«; -} - -fun g() -fun h() -> index: Int? -fun i() -> isTrue: Boolean? diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest index 8bb882026..ac43d44b8 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest @@ -9,4 +9,7 @@ pipeline myPipeline { // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." {"": ""}[»""«]; + + // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." + unresolved[»""«]; } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest index 9799a562b..ee105f4c6 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest @@ -9,4 +9,7 @@ pipeline myPipeline { // $TEST$ error "The receiver of an indexed access must be of type 'List' or 'Map' but was of type 'literal<1>'." »1«[0]; + + // $TEST$ error "The receiver of an indexed access must be of type 'List' or 'Map' but was of type '?'." + »unresolved«[0]; } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest new file mode 100644 index 000000000..9c37be9d5 --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest @@ -0,0 +1,20 @@ +package tests.validation.types.checking.prefixOperations + +segment mySegment() { + + // $TEST$ no error r"The operand of a logical negation must be of type 'Boolean' but was of type .*\." + not »true«; + // $TEST$ error "The operand of a logical negation must be of type 'Boolean' but was of type 'literal<0>'." + not »0«; + // $TEST$ no error r"The operand of a logical negation must be of type 'Boolean' but was of type .*\." + not »unresolved«; + + // $TEST$ no error r"The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type .*\." + -»0.0«; + // $TEST$ no error r"The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type .*\." + -»0«; + // $TEST$ error "The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type 'literal<"">'." + -»""«; + // $TEST$ no error r"The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type .*\." + -»unresolved«; +} From e743dfc45d9d0d386ad3bcea35f10bc111b50d51 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 21:15:54 +0100 Subject: [PATCH 7/9] feat: shorten and normalize error messages --- .../src/language/validation/types.ts | 72 ++---- .../skip-old/infixOperations.sdstest | 230 ------------------ .../types/checking/arguments/main.sdstest | 10 +- .../checking/default values/main.sdstest | 8 +- .../indexed access on list/main.sdstest | 8 +- .../indexed access receiver/main.sdstest | 8 +- .../checking/infix operations/main.sdstest | 130 ++++++++++ .../checking/prefix operations/main.sdstest | 14 +- .../types/checking/yields/main.sdstest | 6 +- 9 files changed, 183 insertions(+), 303 deletions(-) delete mode 100644 packages/safe-ds-lang/tests/resources/validation/skip-old/infixOperations.sdstest create mode 100644 packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index cd2cd662a..cbc7030ea 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -47,15 +47,11 @@ export const argumentTypeMustMatchParameterType = (services: SafeDsServices) => const parameterType = typeComputer.computeType(parameter); if (!typeChecker.isAssignableTo(argumentType, parameterType)) { - accept( - 'error', - `A value of type '${argumentType}' cannot be assigned to a parameter of type '${parameterType}'.`, - { - node, - property: 'value', - code: CODE_TYPE_MISMATCH, - }, - ); + accept('error', `Expected type '${parameterType}' but got '${argumentType}'.`, { + node, + property: 'value', + code: CODE_TYPE_MISMATCH, + }); } }; }; @@ -100,14 +96,10 @@ export const indexedAccessReceiverMustBeListOrMap = (services: SafeDsServices) = return (node: SdsIndexedAccess, accept: ValidationAcceptor): void => { const receiverType = typeComputer.computeType(node.receiver); if (receiverType !== coreTypes.List && receiverType !== coreTypes.Map) { - accept( - 'error', - `The receiver of an indexed access must be of type '${coreTypes.List}' or '${coreTypes.Map}' but was of type '${receiverType}'.`, - { - node: node.receiver, - code: CODE_TYPE_MISMATCH, - }, - ); + accept('error', `Expected type '${coreTypes.List}' or '${coreTypes.Map}' but got '${receiverType}'.`, { + node: node.receiver, + code: CODE_TYPE_MISMATCH, + }); } }; }; @@ -122,15 +114,11 @@ export const indexedAccessIndexMustHaveCorrectType = (services: SafeDsServices) if (receiverType === coreTypes.List) { const indexType = typeComputer.computeType(node.index); if (!typeChecker.isAssignableTo(indexType, coreTypes.Int)) { - accept( - 'error', - `The index of an indexed access on a list must be of type '${coreTypes.Int}' but was of type '${indexType}'.`, - { - node, - property: 'index', - code: CODE_TYPE_MISMATCH, - }, - ); + accept('error', `Expected type '${coreTypes.Int}' but got '${indexType}'.`, { + node, + property: 'index', + code: CODE_TYPE_MISMATCH, + }); } } }; @@ -150,15 +138,11 @@ export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDs const parameterType = typeComputer.computeType(node); if (!typeChecker.isAssignableTo(defaultValueType, parameterType)) { - accept( - 'error', - `A default value of type '${defaultValueType}' cannot be assigned to a parameter of type '${parameterType}'.`, - { - node, - property: 'defaultValue', - code: CODE_TYPE_MISMATCH, - }, - ); + accept('error', `Expected type '${parameterType}' but got '${defaultValueType}'.`, { + node, + property: 'defaultValue', + code: CODE_TYPE_MISMATCH, + }); } }; }; @@ -173,15 +157,11 @@ export const prefixOperationOperandMustHaveCorrectType = (services: SafeDsServic switch (node.operator) { case 'not': if (!typeChecker.isAssignableTo(operandType, coreTypes.Boolean)) { - accept( - 'error', - `The operand of a logical negation must be of type '${coreTypes.Boolean}' but was of type '${operandType}'.`, - { - node, - property: 'operand', - code: CODE_TYPE_MISMATCH, - }, - ); + accept('error', `Expected type '${coreTypes.Boolean}' but got '${operandType}'.`, { + node, + property: 'operand', + code: CODE_TYPE_MISMATCH, + }); } return; case '-': @@ -191,7 +171,7 @@ export const prefixOperationOperandMustHaveCorrectType = (services: SafeDsServic ) { accept( 'error', - `The operand of an arithmetic negation must be of type '${coreTypes.Float}' or '${coreTypes.Int}' but was of type '${operandType}'.`, + `Expected type '${coreTypes.Float}' or '${coreTypes.Int}' but got '${operandType}'.`, { node, property: 'operand', @@ -218,7 +198,7 @@ export const yieldTypeMustMatchResultType = (services: SafeDsServices) => { const resultType = typeComputer.computeType(result); if (!typeChecker.isAssignableTo(yieldType, resultType)) { - accept('error', `A value of type '${yieldType}' cannot be assigned to a result of type '${resultType}'.`, { + accept('error', `Expected type '${resultType}' but got '${yieldType}'.`, { node, property: 'result', code: CODE_TYPE_MISMATCH, diff --git a/packages/safe-ds-lang/tests/resources/validation/skip-old/infixOperations.sdstest b/packages/safe-ds-lang/tests/resources/validation/skip-old/infixOperations.sdstest deleted file mode 100644 index 418927427..000000000 --- a/packages/safe-ds-lang/tests/resources/validation/skip-old/infixOperations.sdstest +++ /dev/null @@ -1,230 +0,0 @@ -package tests.validation.typeChecking.infixOperations - -step f(vararg a: Int) { - - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »true« or »true« ; - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »false« or »false«; - // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »i()« or »i()«; - // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »0« or »0«; - // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »a« or »a«; - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »unresolved« or »unresolved«; - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »C.unresolved« or »C.unresolved«; - - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »true« and »true«; - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »false« and »false«; - // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »i()« and »i()«; - // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »0« and »0«; - // $TEST$ error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »a« and »a«; - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »unresolved« and »unresolved«; - // $TEST$ no error "The left operand of a logical infix operation must be an instance of the class 'Boolean'." - // $TEST$ no error "The right operand of a logical infix operation must be an instance of the class 'Boolean'." - »C.unresolved« and »C.unresolved«; - - - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0.0« + »0.0«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0« + »0«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »h()« + »h()«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »""« + »""«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »a« + »a«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »unresolved« + »unresolved«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« + »C.unresolved«; - - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0.0« - »0.0«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0« - »0«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »h()« - »h()«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »""« - »""«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »a« - »a«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »unresolved« - »unresolved«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« - »C.unresolved«; - - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0.0« * »0.0«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0« * »0«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »h()« * »h()«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »""« * »""«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »a« * »a«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »unresolved« * »unresolved«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« * »C.unresolved«; - - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0.0« / »0.0«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »0« / »0«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »h()« / »h()«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »""« / »""«; - // $TEST$ error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »a« / »a«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »unresolved« / »unresolved«; - // $TEST$ no error "The left operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of an arithmetic infix operation must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« / »C.unresolved«; - - - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0.0« < »0.0«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0« < »0«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »h()« < »h()«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »""« < »""«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »a« < »a«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »unresolved« < »unresolved«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« < »C.unresolved«; - - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0.0« <= »0.0«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0« <= »0«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »h()« <= »h()«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »""« <= »""«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »a« <= »a«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »unresolved« <= »unresolved«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« <= »C.unresolved«; - - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0.0« >= »0.0«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0« >= »0«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »h()« >= »h()«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »""« >= »""«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »a« >= »a«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »unresolved« >= »unresolved«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« >= »C.unresolved«; - - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0.0« > »0.0«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »0« > »0«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »h()« > »h()«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »""« > »""«; - // $TEST$ error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »a« > »a«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »unresolved« > »unresolved«; - // $TEST$ no error "The left operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - // $TEST$ no error "The right operand of a comparison must be an instance of the class 'Float' or the class 'Int'." - »C.unresolved« > »C.unresolved«; -} - -fun g() -fun h() -> index: Int? -fun i() -> isTrue: Boolean? diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest index f7a098e7f..95aa5c2f3 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/arguments/main.sdstest @@ -3,18 +3,18 @@ package tests.validation.types.checking.arguments fun f(p: Int) segment mySegment() { - // $TEST$ no error r"A value of type .* cannot be assigned to a parameter of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." f(»1«); - // $TEST$ no error r"A value of type .* cannot be assigned to a parameter of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." f(p = »1«); - // $TEST$ error "A value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + // $TEST$ error "Expected type 'Int' but got 'literal<"">'." f(»""«); - // $TEST$ error "A value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + // $TEST$ error "Expected type 'Int' but got 'literal<"">'." f(p = »""«); - // $TEST$ no error r"A value of type .* cannot be assigned to a parameter of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." f(unresolved = »1«); } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest index 9cee4b5c4..8dd59f9b0 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/default values/main.sdstest @@ -1,19 +1,19 @@ package tests.validation.types.checking.defaultValues fun myFun( - // $TEST$ no error r"A default value of type .* cannot be assigned to a parameter of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." param1: Int = »1«, - // $TEST$ error "A default value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + // $TEST$ error "Expected type 'Int' but got 'literal<"">'." param2: Int = »""«, ) fun myOtherFun(callback: (a: Int) -> ()) segment mySegment() { - // $TEST$ no error r"A default value of type .* cannot be assigned to a parameter of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." myOtherFun((a = »1«) {}); - // $TEST$ error "A default value of type 'literal<"">' cannot be assigned to a parameter of type 'Int'." + // $TEST$ error "Expected type 'Int' but got 'literal<"">'." myOtherFun((a = »""«) {}); } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest index ac43d44b8..bd29412a0 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access on list/main.sdstest @@ -1,15 +1,15 @@ package tests.validation.types.checking.indexedAccessOnList pipeline myPipeline { - // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." + // $TEST$ no error r"Expected type 'Int' but got .*\." [1][»0«]; - // $TEST$ error "The index of an indexed access on a list must be of type 'Int' but was of type 'literal<"">'." + // $TEST$ error "Expected type 'Int' but got 'literal<"">'." [0][»""«]; - // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." + // $TEST$ no error r"Expected type 'Int' but got .*\." {"": ""}[»""«]; - // $TEST$ no error r"The index of an indexed access on a list must be of type 'Int' but was of type .*\." + // $TEST$ no error r"Expected type 'Int' but got .*\." unresolved[»""«]; } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest index ee105f4c6..eddbf11ea 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/indexed access receiver/main.sdstest @@ -1,15 +1,15 @@ package tests.validation.types.checking.indexedAccessReceiver pipeline myPipeline { - // $TEST$ no error r"The receiver of an indexed access must be of type 'List' or 'Map' but was of type .*\." + // $TEST$ no error r"Expected type 'List' or 'Map' but got .*\." »[1]«[0]; - // $TEST$ no error r"The receiver of an indexed access must be of type 'List' or 'Map' but was of type .*\." + // $TEST$ no error r"Expected type 'List' or 'Map' but got .*\." »{0: 1}«[0]; - // $TEST$ error "The receiver of an indexed access must be of type 'List' or 'Map' but was of type 'literal<1>'." + // $TEST$ error "Expected type 'List' or 'Map' but got 'literal<1>'." »1«[0]; - // $TEST$ error "The receiver of an indexed access must be of type 'List' or 'Map' but was of type '?'." + // $TEST$ error "Expected type 'List' or 'Map' but got '?'." »unresolved«[0]; } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest new file mode 100644 index 000000000..ef3e5b9aa --- /dev/null +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest @@ -0,0 +1,130 @@ +package tests.validation.types.checking.infixOperations + +pipeline myPipeline { + + // $TEST$ no error r"Expected type 'Boolean' but got .*\." + // $TEST$ no error r"Expected type 'Boolean' but got .*\." + »true« or »true« ; + // $TEST$ error "Expected type 'Boolean' but got 'literal<0>'." + // $TEST$ error "Expected type 'Boolean' but got 'literal<0>'." + »0« or »0«; + // $TEST$ error "Expected type 'Boolean' but got '?'." + // $TEST$ error "Expected type 'Boolean' but got '?'." + »unresolved« or »unresolved«; + + // $TEST$ no error r"Expected type 'Boolean' but got .*\." + // $TEST$ no error r"Expected type 'Boolean' but got .*\." + »true« and »true«; + // $TEST$ error "Expected type 'Boolean' but got 'literal<0>'." + // $TEST$ error "Expected type 'Boolean' but got 'literal<0>'." + »0« and »0«; + // $TEST$ error "Expected type 'Boolean' but got '?'." + // $TEST$ error "Expected type 'Boolean' but got '?'." + »unresolved« and »unresolved«; + + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« + »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« + »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« + »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« + »unresolved«; + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« - »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« - »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« - »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« - »unresolved«; + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« * »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« * »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« * »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« * »unresolved«; + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« / »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« / »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« / »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« / »unresolved«; + + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« < »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« < »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« < »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« < »unresolved«; + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« <= »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« <= »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« <= »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« <= »unresolved«; + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« >= »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« >= »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« >= »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« >= »unresolved«; + + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0.0« > »0.0«; + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." + »0« > »0«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »""« > »""«; + // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int'." + »unresolved« > »unresolved«; +} diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest index 9c37be9d5..275f0f79b 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/prefix operations/main.sdstest @@ -2,19 +2,19 @@ package tests.validation.types.checking.prefixOperations segment mySegment() { - // $TEST$ no error r"The operand of a logical negation must be of type 'Boolean' but was of type .*\." + // $TEST$ no error r"Expected type 'Boolean' but got .*\." not »true«; - // $TEST$ error "The operand of a logical negation must be of type 'Boolean' but was of type 'literal<0>'." + // $TEST$ error "Expected type 'Boolean' but got 'literal<0>'." not »0«; - // $TEST$ no error r"The operand of a logical negation must be of type 'Boolean' but was of type .*\." + // $TEST$ error "Expected type 'Boolean' but got '?'." not »unresolved«; - // $TEST$ no error r"The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." -»0.0«; - // $TEST$ no error r"The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type .*\." + // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." -»0«; - // $TEST$ error "The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." -»""«; - // $TEST$ no error r"The operand of an arithmetic negation must be of type 'Float' or 'Int' but was of type .*\." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." -»unresolved«; } diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest index 9d1ace530..79a363dfd 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/yields/main.sdstest @@ -1,16 +1,16 @@ package tests.validation.types.checking.yields segment mySegment1() -> result: Int { - // $TEST$ no error r"A value of type .* cannot be assigned to a result of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." yield »result« = 1; } segment mySegment2() -> result: Int { - // $TEST$ error "A value of type 'literal<"">' cannot be assigned to a result of type 'Int'." + // $TEST$ error "Expected type 'Int' but got 'literal<"">'." yield »result« = ""; } segment mySegment3() { - // $TEST$ no error r"A value of type .* cannot be assigned to a result of type .*\." + // $TEST$ no error r"Expected type .* but got .*\." yield »unresolved« = 1; } From 35a90a65ad20e18667ed502e79d8eafcb888e0b2 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 21:39:49 +0100 Subject: [PATCH 8/9] feat: type checking for infix operations --- .../language/validation/safe-ds-validator.ts | 7 +- .../src/language/validation/types.ts | 60 +++++++++++++++++ .../checking/infix operations/main.sdstest | 64 +++++++++---------- 3 files changed, 98 insertions(+), 33 deletions(-) diff --git a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts index bb3c89d0a..0d950be89 100644 --- a/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts +++ b/packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts @@ -49,6 +49,7 @@ import { callReceiverMustBeCallable, indexedAccessIndexMustHaveCorrectType, indexedAccessReceiverMustBeListOrMap, + infixOperationOperandsMustHaveCorrectType, namedTypeMustSetAllTypeParameters, parameterDefaultValueTypeMustMatchParameterType, parameterMustHaveTypeHint, @@ -238,7 +239,11 @@ export const registerValidationChecks = function (services: SafeDsServices) { indexedAccessReceiverMustBeListOrMap(services), indexedAccessesShouldBeUsedWithCaution, ], - SdsInfixOperation: [divisionDivisorMustNotBeZero(services), elvisOperatorShouldBeNeeded(services)], + SdsInfixOperation: [ + divisionDivisorMustNotBeZero(services), + elvisOperatorShouldBeNeeded(services), + infixOperationOperandsMustHaveCorrectType(services), + ], SdsLambda: [ lambdaMustBeAssignedToTypedParameter(services), lambdaParametersMustNotBeAnnotated, diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index cbc7030ea..c3ef9c542 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -12,6 +12,7 @@ import { SdsAttribute, SdsCall, SdsIndexedAccess, + SdsInfixOperation, SdsNamedType, SdsParameter, SdsPrefixOperation, @@ -124,6 +125,65 @@ export const indexedAccessIndexMustHaveCorrectType = (services: SafeDsServices) }; }; +export const infixOperationOperandsMustHaveCorrectType = (services: SafeDsServices) => { + const coreTypes = services.types.CoreTypes; + const typeChecker = services.types.TypeChecker; + const typeComputer = services.types.TypeComputer; + + return (node: SdsInfixOperation, accept: ValidationAcceptor): void => { + const leftType = typeComputer.computeType(node.leftOperand); + const rightType = typeComputer.computeType(node.rightOperand); + switch (node.operator) { + case 'or': + case 'and': + if (!typeChecker.isAssignableTo(leftType, coreTypes.Boolean)) { + accept('error', `Expected type '${coreTypes.Boolean}' but got '${leftType}'.`, { + node: node.leftOperand, + code: CODE_TYPE_MISMATCH, + }); + } + if (!typeChecker.isAssignableTo(rightType, coreTypes.Boolean)) { + accept('error', `Expected type '${coreTypes.Boolean}' but got '${rightType}'.`, { + node: node.rightOperand, + code: CODE_TYPE_MISMATCH, + }); + } + return; + case '<': + case '<=': + case '>=': + case '>': + case '+': + case '-': + case '*': + case '/': + if ( + !typeChecker.isAssignableTo(leftType, coreTypes.Float) && + !typeChecker.isAssignableTo(leftType, coreTypes.Int) + ) { + accept('error', `Expected type '${coreTypes.Float}' or '${coreTypes.Int}' but got '${leftType}'.`, { + node: node.leftOperand, + code: CODE_TYPE_MISMATCH, + }); + } + if ( + !typeChecker.isAssignableTo(rightType, coreTypes.Float) && + !typeChecker.isAssignableTo(rightType, coreTypes.Int) + ) { + accept( + 'error', + `Expected type '${coreTypes.Float}' or '${coreTypes.Int}' but got '${rightType}'.`, + { + node: node.rightOperand, + code: CODE_TYPE_MISMATCH, + }, + ); + } + return; + } + }; +}; + export const parameterDefaultValueTypeMustMatchParameterType = (services: SafeDsServices) => { const typeChecker = services.types.TypeChecker; const typeComputer = services.types.TypeComputer; diff --git a/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest b/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest index ef3e5b9aa..a4686c1b3 100644 --- a/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest +++ b/packages/safe-ds-lang/tests/resources/validation/types/checking/infix operations/main.sdstest @@ -29,11 +29,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« + »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« + »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« + »unresolved«; // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." @@ -42,11 +42,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« - »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« - »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« - »unresolved«; // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." @@ -55,11 +55,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« * »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« * »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« * »unresolved«; // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." @@ -68,11 +68,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« / »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« / »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« / »unresolved«; @@ -82,11 +82,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« < »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« < »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« < »unresolved«; // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." @@ -95,11 +95,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« <= »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« <= »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« <= »unresolved«; // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." @@ -108,11 +108,11 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« >= »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« >= »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« >= »unresolved«; // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." @@ -121,10 +121,10 @@ pipeline myPipeline { // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." // $TEST$ no error r"Expected type 'Float' or 'Int' but got .*\." »0« > »0«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." + // $TEST$ error "Expected type 'Float' or 'Int' but got 'literal<"">'." »""« > »""«; - // $TEST$ error "Expected type 'Float' or 'Int'." - // $TEST$ error "Expected type 'Float' or 'Int'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." + // $TEST$ error "Expected type 'Float' or 'Int' but got '?'." »unresolved« > »unresolved«; } From 67f3348912a8e4d17805266601469f519a83852a Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 4 Nov 2023 22:23:04 +0100 Subject: [PATCH 9/9] test: adjust tests --- .../src/language/typing/safe-ds-type-checker.ts | 5 +---- packages/safe-ds-lang/src/language/validation/types.ts | 8 ++++++-- .../tests/language/typing/safe-ds-type-checker.test.ts | 2 +- .../declarations/parameter with python name/input.sdstest | 4 ++-- .../tests/generator/parameterWithPythonName/gen_input.py | 4 ++-- .../generator/parameterWithPythonName/gen_input.py.map | 2 +- .../generation/expressions/block lambda/input.sdstest | 2 +- .../output/tests/generator/blockLambda/gen_input.py | 2 +- .../output/tests/generator/blockLambda/gen_input.py.map | 2 +- .../expressions/expression lambda/input.sdstest | 2 +- .../output/tests/generator/expressionLambda/gen_input.py | 2 +- .../tests/generator/expressionLambda/gen_input.py.map | 2 +- .../generation/expressions/member access/input.sdstest | 2 +- 13 files changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts b/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts index d3dbe3ca8..70ff1dc3b 100644 --- a/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts +++ b/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts @@ -105,10 +105,7 @@ export class SafeDsTypeChecker { const typeEntry = type.outputType.entries[i]; const otherEntry = other.outputType.entries[i]; - // Names must match - if (typeEntry.name !== otherEntry.name) { - return false; - } + // Names must not match since we always fetch results by index // Types must be covariant if (!this.isAssignableTo(typeEntry.type, otherEntry.type)) { diff --git a/packages/safe-ds-lang/src/language/validation/types.ts b/packages/safe-ds-lang/src/language/validation/types.ts index c3ef9c542..b1fb4e5e2 100644 --- a/packages/safe-ds-lang/src/language/validation/types.ts +++ b/packages/safe-ds-lang/src/language/validation/types.ts @@ -92,11 +92,15 @@ export const callReceiverMustBeCallable = (services: SafeDsServices) => { export const indexedAccessReceiverMustBeListOrMap = (services: SafeDsServices) => { const coreTypes = services.types.CoreTypes; + const typeChecker = services.types.TypeChecker; const typeComputer = services.types.TypeComputer; return (node: SdsIndexedAccess, accept: ValidationAcceptor): void => { const receiverType = typeComputer.computeType(node.receiver); - if (receiverType !== coreTypes.List && receiverType !== coreTypes.Map) { + if ( + !typeChecker.isAssignableTo(receiverType, coreTypes.List) && + !typeChecker.isAssignableTo(receiverType, coreTypes.Map) + ) { accept('error', `Expected type '${coreTypes.List}' or '${coreTypes.Map}' but got '${receiverType}'.`, { node: node.receiver, code: CODE_TYPE_MISMATCH, @@ -112,7 +116,7 @@ export const indexedAccessIndexMustHaveCorrectType = (services: SafeDsServices) return (node: SdsIndexedAccess, accept: ValidationAcceptor): void => { const receiverType = typeComputer.computeType(node.receiver); - if (receiverType === coreTypes.List) { + if (typeChecker.isAssignableTo(receiverType, coreTypes.List)) { const indexType = typeComputer.computeType(node.index); if (!typeChecker.isAssignableTo(indexType, coreTypes.Int)) { accept('error', `Expected type '${coreTypes.Int}' but got '${indexType}'.`, { diff --git a/packages/safe-ds-lang/tests/language/typing/safe-ds-type-checker.test.ts b/packages/safe-ds-lang/tests/language/typing/safe-ds-type-checker.test.ts index bf7e44c59..d1e8e5b6b 100644 --- a/packages/safe-ds-lang/tests/language/typing/safe-ds-type-checker.test.ts +++ b/packages/safe-ds-lang/tests/language/typing/safe-ds-type-checker.test.ts @@ -144,7 +144,7 @@ describe('SafeDsTypeChecker', async () => { { type1: callableType8, type2: callableType7, - expected: false, + expected: true, }, { type1: callableType9, diff --git a/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/input.sdstest b/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/input.sdstest index c6b48eed9..3fa0240f6 100644 --- a/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/input.sdstest +++ b/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/input.sdstest @@ -4,6 +4,6 @@ fun f1(param: (a: Int, b: Int, c: Int) -> r: Int) fun f2(param: (a: Int, b: Int, c: Int) -> ()) segment test(param1: Int, @PythonName("param_2") param2: Int, @PythonName("param_3") param3: Int = 0) { - f1((param1: Int, param2: Int, param3: Int = 0) -> 1); - f2((param1: Int, param2: Int, param3: Int = 0) {}); + f1((a: Int, b: Int, c: Int = 0) -> 1); + f2((a: Int, b: Int, c: Int = 0) {}); } diff --git a/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py b/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py index ae228dbf2..f48810d87 100644 --- a/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py +++ b/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py @@ -1,7 +1,7 @@ # Segments --------------------------------------------------------------------- def test(param1, param_2, param_3=0): - f1(lambda param1, param2, param3=0: 1) - def __gen_block_lambda_0(param1, param2, param3=0): + f1(lambda a, b, c=0: 1) + def __gen_block_lambda_0(a, b, c=0): pass f2(__gen_block_lambda_0) diff --git a/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py.map b/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py.map index 4b451a86c..bbe73b1bf 100644 --- a/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py.map +++ b/packages/safe-ds-lang/tests/resources/generation/declarations/parameter with python name/output/tests/generator/parameterWithPythonName/gen_input.py.map @@ -1 +1 @@ -{"version":3,"sources":["input.sdstest"],"names":["test","param1","param2","param3","f1","f2"],"mappings":"AAAA;;AAKA,IAAQA,IAAI,CAACC,MAAM,EAA8BC,OAAM,EAA8BC,OAAM,CAAQ,CAAC;IAChGC,EAAE,CAAC,OAACH,MAAM,EAAOC,MAAM,EAAOC,MAAM,CAAQ,CAAC,EAAK,CAAC;IAChD,yBAACF,MAAM,EAAOC,MAAM,EAAOC,MAAM,CAAQ,CAAC;QAAE,IAAE;IAAjDE,EAAE,CAAC","file":"gen_input.py"} \ No newline at end of file +{"version":3,"sources":["input.sdstest"],"names":["test","param1","param2","param3","f1","a","b","c","f2"],"mappings":"AAAA;;AAKA,IAAQA,IAAI,CAACC,MAAM,EAA8BC,OAAM,EAA8BC,OAAM,CAAQ,CAAC;IAChGC,EAAE,CAAC,OAACC,CAAC,EAAOC,CAAC,EAAOC,CAAC,CAAQ,CAAC,EAAK,CAAC;IACjC,yBAACF,CAAC,EAAOC,CAAC,EAAOC,CAAC,CAAQ,CAAC;QAAE,IAAE;IAAlCC,EAAE,CAAC","file":"gen_input.py"} \ No newline at end of file diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/input.sdstest b/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/input.sdstest index bdfcd497c..408b1159b 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/input.sdstest +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/input.sdstest @@ -9,7 +9,7 @@ pipeline test { f1((a: Int, b: Int = 2) { yield d = g(); }); - f1((a: Int, c: Int) { + f1((a: Int, b: Int) { yield d = g(); }); f2(() {}); diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py b/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py index 1f02920f7..4ab7b98a8 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py @@ -5,7 +5,7 @@ def __gen_block_lambda_0(a, b=2): __gen_block_lambda_result_d = g() return __gen_block_lambda_result_d f1(__gen_block_lambda_0) - def __gen_block_lambda_1(a, c): + def __gen_block_lambda_1(a, b): __gen_block_lambda_result_d = g() return __gen_block_lambda_result_d f1(__gen_block_lambda_1) diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py.map b/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py.map index 353842a02..242999d3f 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py.map +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/block lambda/output/tests/generator/blockLambda/gen_input.py.map @@ -1 +1 @@ -{"version":3,"sources":["input.sdstest"],"names":["test","a","b","d","g","f1","c","f2"],"mappings":"AAAA;;AAOA,IAASA,IAAI;IACN,yBAACC,CAAC,EAAOC,CAAC,CAAQ,CAAC;QAClB,0BAAMC,CAAC,GAAGC,CAAC;QADZ,OACC,0BAAMD,CAAC;IADXE,EAAE,CAAC;IAGA,yBAACJ,CAAC,EAAOK,CAAC;QACT,0BAAMH,CAAC,GAAGC,CAAC;QADZ,OACC,0BAAMD,CAAC;IADXE,EAAE,CAAC;IAGA;QAAG,IAAE;IAARE,EAAE,CAAC","file":"gen_input.py"} \ No newline at end of file +{"version":3,"sources":["input.sdstest"],"names":["test","a","b","d","g","f1","f2"],"mappings":"AAAA;;AAOA,IAASA,IAAI;IACN,yBAACC,CAAC,EAAOC,CAAC,CAAQ,CAAC;QAClB,0BAAMC,CAAC,GAAGC,CAAC;QADZ,OACC,0BAAMD,CAAC;IADXE,EAAE,CAAC;IAGA,yBAACJ,CAAC,EAAOC,CAAC;QACT,0BAAMC,CAAC,GAAGC,CAAC;QADZ,OACC,0BAAMD,CAAC;IADXE,EAAE,CAAC;IAGA;QAAG,IAAE;IAARC,EAAE,CAAC","file":"gen_input.py"} \ No newline at end of file diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/input.sdstest b/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/input.sdstest index 6f39b97ec..153bdb4a5 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/input.sdstest +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/input.sdstest @@ -4,5 +4,5 @@ fun f(param: (a: Int, b: Int) -> r: Int) pipeline test { f((a, b = 2) -> 1); - f((a, c) -> 1); + f((a, b) -> 1); } diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py b/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py index 7f130276a..ad30c61c5 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py @@ -2,4 +2,4 @@ def test(): f(lambda a, b=2: 1) - f(lambda a, c: 1) + f(lambda a, b: 1) diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py.map b/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py.map index db976a153..38b178bd0 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py.map +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/expression lambda/output/tests/generator/expressionLambda/gen_input.py.map @@ -1 +1 @@ -{"version":3,"sources":["input.sdstest"],"names":["test","f","a","b","c"],"mappings":"AAAA;;AAIA,IAASA,IAAI;IACTC,CAAC,CAAC,OAACC,CAAC,EAAEC,CAAC,CAAG,CAAC,EAAK,CAAC;IACjBF,CAAC,CAAC,OAACC,CAAC,EAAEE,CAAC,EAAK,CAAC","file":"gen_input.py"} \ No newline at end of file +{"version":3,"sources":["input.sdstest"],"names":["test","f","a","b"],"mappings":"AAAA;;AAIA,IAASA,IAAI;IACTC,CAAC,CAAC,OAACC,CAAC,EAAEC,CAAC,CAAG,CAAC,EAAK,CAAC;IACjBF,CAAC,CAAC,OAACC,CAAC,EAAEC,CAAC,EAAK,CAAC","file":"gen_input.py"} \ No newline at end of file diff --git a/packages/safe-ds-lang/tests/resources/generation/expressions/member access/input.sdstest b/packages/safe-ds-lang/tests/resources/generation/expressions/member access/input.sdstest index 71a924027..5e52b3b23 100644 --- a/packages/safe-ds-lang/tests/resources/generation/expressions/member access/input.sdstest +++ b/packages/safe-ds-lang/tests/resources/generation/expressions/member access/input.sdstest @@ -10,7 +10,7 @@ class C() { attr a: Int @PythonName("c") attr b: Int - @PythonCall("$param.i($this)") fun i(param: Any?) + @PythonCall("$param.i($this)") fun i(param: Any?) -> result: Boolean } fun factory() -> instance: C?