1
1
import { assertUnreachable } from "langium" ;
2
2
import { isExpression , isNumberLiteral , isStringLiteral , Pl1AstType } from "../generated/ast" ;
3
3
import { TypesDescriptions } from "./descriptions" ;
4
+ import { ArithmeticOperator , createArithmeticOperationTable } from "./arithmetic-operations" ;
4
5
5
6
export type PliAstNode = Pl1AstType [ keyof Pl1AstType ] ;
6
7
@@ -9,63 +10,90 @@ export interface PliTypeInferer {
9
10
}
10
11
11
12
export class DefaultPliTypeInferer implements PliTypeInferer {
13
+ private inferArithmeticOperation : ( { op, lhs, rhs } : { op : ArithmeticOperator ; lhs : TypesDescriptions . Arithmetic ; rhs : TypesDescriptions . Arithmetic ; } ) => TypesDescriptions . Any | undefined ;
14
+ constructor ( ) {
15
+ /** @todo pass in the compiler flag RULES(X), where X = 'ans' or 'ibm' */
16
+ this . inferArithmeticOperation = createArithmeticOperationTable ( 'ans' ) ;
17
+ }
12
18
/** @todo multiple entry points: for Expression, VariableDecl, Entries? */
13
19
inferType ( node : PliAstNode ) : TypesDescriptions . Any | undefined {
14
20
if ( isExpression ( node ) ) {
15
21
switch ( node . $type ) {
16
22
case "BinaryExpression" :
17
- //@see https://www.ibm.com/docs/en/epfz/6.1?topic=operations-results-arithmetic
18
23
switch ( node . op ) {
19
- case "!!" :
20
- case "&" :
21
- case "*" :
22
- case "**" :
23
24
case "+" :
24
25
case "-" :
26
+ case "*" :
25
27
case "/" :
28
+ case "**" : {
29
+ //@see https://www.ibm.com/docs/en/epfz/6.1?topic=operations-results-arithmetic
30
+ const op = node . op ;
31
+ const lhs = this . inferType ( node . left ) ;
32
+ const rhs = this . inferType ( node . right ) ;
33
+ if ( ! lhs || ! rhs || ! TypesDescriptions . isArithmetic ( lhs ) || ! TypesDescriptions . isArithmetic ( rhs ) ) {
34
+ /** @todo also take care of this branch */
35
+ return undefined ;
36
+ }
37
+ return this . inferArithmeticOperation ( { op, lhs, rhs } )
38
+ }
39
+ case "<" :
40
+ case "<=" :
41
+ case "<>" :
42
+ case "=" :
43
+ case ">" :
44
+ case ">=" : {
45
+ return TypesDescriptions . Boolean ;
46
+ }
26
47
case "^" :
48
+ case "!!" :
49
+ case "&" :
27
50
case "^=" :
28
51
case "|" :
29
52
case "||" :
30
53
case "¬" :
31
54
case "¬<" :
32
55
case "¬=" :
33
- case "¬>" :
34
- break ;
35
- case "<" :
36
- case "<=" :
37
- case "<>" :
38
- case "=" :
39
- case ">" :
40
- case ">=" :
41
- return TypesDescriptions . Boolean ;
56
+ case "¬>" : {
57
+ /** @todo */
58
+ return undefined ;
59
+ }
42
60
default :
43
61
assertUnreachable ( node )
44
62
}
45
- break ;
46
63
case "UnaryExpression" :
47
64
switch ( node . op ) {
48
65
case "+" :
49
- case "-" :
50
- case "^" :
51
- case "¬" :
52
- break ;
66
+ case "-" : {
67
+ /** @todo what about negating vs. sign of the type */
68
+ return this . inferType ( node . expr ) ;
69
+ }
70
+ case "^" : {
71
+ /** @todo */
72
+ return undefined ;
73
+ }
74
+ case "¬" : {
75
+ return TypesDescriptions . Boolean ;
76
+ }
53
77
default :
54
78
assertUnreachable ( node )
55
79
}
56
- break ;
57
80
case "Literal" :
58
81
if ( isStringLiteral ( node . value ) ) {
59
-
82
+ /** @todo */
83
+ return undefined ;
60
84
} else if ( isNumberLiteral ( node . value ) ) {
61
-
85
+ /** @todo */
86
+ return undefined ;
62
87
} else {
63
88
assertUnreachable ( node . value ) ;
64
89
}
65
- break ;
66
- case "LocatorCall" :
90
+ case "LocatorCall" : {
67
91
//node.previous -> node.element
68
- break ;
92
+ /** @todo */
93
+ return undefined ;
94
+ }
95
+ default :
96
+ assertUnreachable ( node ) ;
69
97
}
70
98
}
71
99
return undefined ;
0 commit comments