1
1
import { getContainerOfType } from 'langium' ;
2
2
import type { SafeDsClasses } from '../builtins/safe-ds-classes.js' ;
3
- import { isSdsEnum , SdsDeclaration } from '../generated/ast.js' ;
3
+ import { isSdsEnum , type SdsAbstractResult , SdsDeclaration } from '../generated/ast.js' ;
4
+ import { getParameters } from '../helpers/nodeProperties.js' ;
4
5
import {
5
6
BooleanConstant ,
6
7
Constant ,
@@ -16,6 +17,7 @@ import {
16
17
EnumType ,
17
18
EnumVariantType ,
18
19
LiteralType ,
20
+ NamedTupleEntry ,
19
21
NamedTupleType ,
20
22
StaticType ,
21
23
Type ,
@@ -24,16 +26,19 @@ import {
24
26
} from './model.js' ;
25
27
import { SafeDsClassHierarchy } from './safe-ds-class-hierarchy.js' ;
26
28
import { SafeDsCoreTypes } from './safe-ds-core-types.js' ;
29
+ import type { SafeDsTypeComputer } from './safe-ds-type-computer.js' ;
27
30
28
31
export class SafeDsTypeChecker {
29
32
private readonly builtinClasses : SafeDsClasses ;
30
33
private readonly classHierarchy : SafeDsClassHierarchy ;
31
34
private readonly coreTypes : SafeDsCoreTypes ;
35
+ private readonly typeComputer : ( ) => SafeDsTypeComputer ;
32
36
33
37
constructor ( services : SafeDsServices ) {
34
38
this . builtinClasses = services . builtins . Classes ;
35
39
this . classHierarchy = services . types . ClassHierarchy ;
36
40
this . coreTypes = services . types . CoreTypes ;
41
+ this . typeComputer = ( ) => services . types . TypeComputer ;
37
42
}
38
43
39
44
/**
@@ -218,8 +223,48 @@ export class SafeDsTypeChecker {
218
223
}
219
224
}
220
225
221
- private staticTypeIsAssignableTo ( type : Type , other : Type ) : boolean {
222
- return type . equals ( other ) ;
226
+ private staticTypeIsAssignableTo ( type : StaticType , other : Type ) : boolean {
227
+ if ( other instanceof CallableType ) {
228
+ return this . isAssignableTo ( this . associatedCallableTypeForStaticType ( type ) , other ) ;
229
+ } else {
230
+ return type . equals ( other ) ;
231
+ }
232
+ }
233
+
234
+ private associatedCallableTypeForStaticType ( type : StaticType ) : Type {
235
+ const instanceType = type . instanceType ;
236
+ if ( instanceType instanceof ClassType ) {
237
+ const declaration = instanceType . declaration ;
238
+ if ( ! declaration . parameterList ) {
239
+ return UnknownType ;
240
+ }
241
+
242
+ const parameterEntries = new NamedTupleType (
243
+ ...getParameters ( declaration ) . map (
244
+ ( it ) => new NamedTupleEntry ( it , it . name , this . typeComputer ( ) . computeType ( it ) ) ,
245
+ ) ,
246
+ ) ;
247
+ const resultEntries = new NamedTupleType (
248
+ new NamedTupleEntry < SdsAbstractResult > ( undefined , 'instance' , instanceType ) ,
249
+ ) ;
250
+
251
+ return new CallableType ( declaration , parameterEntries , resultEntries ) ;
252
+ } else if ( instanceType instanceof EnumVariantType ) {
253
+ const declaration = instanceType . declaration ;
254
+
255
+ const parameterEntries = new NamedTupleType (
256
+ ...getParameters ( declaration ) . map (
257
+ ( it ) => new NamedTupleEntry ( it , it . name , this . typeComputer ( ) . computeType ( it ) ) ,
258
+ ) ,
259
+ ) ;
260
+ const resultEntries = new NamedTupleType (
261
+ new NamedTupleEntry < SdsAbstractResult > ( undefined , 'instance' , instanceType ) ,
262
+ ) ;
263
+
264
+ return new CallableType ( declaration , parameterEntries , resultEntries ) ;
265
+ } else {
266
+ return UnknownType ;
267
+ }
223
268
}
224
269
225
270
private unionTypeIsAssignableTo ( type : UnionType , other : Type ) : boolean {
0 commit comments