-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
descriptions.ts
154 lines (123 loc) · 3.34 KB
/
descriptions.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import type {AstNode} from 'langium'
import type {Identifier, NumberLiteral, TypeExpression} from '../generated/ast.js'
export type TypeDescription = NumberType | FunctionType | TypeInferenceError
type NumberType = LiteralNumberType | I32NumberType | F64NumberType | F32NumberType
// number
export interface LiteralNumberType {
readonly $type: 'number'
readonly literal?: NumberLiteral
}
export function createLiteralNumberType(literal?: NumberLiteral): LiteralNumberType {
return {
$type: 'number',
literal,
}
}
export function isLiteralNumberType(item: TypeDescription): item is LiteralNumberType {
return item.$type === 'number'
}
// i32
export interface I32NumberType {
readonly $type: 'i32'
readonly literal?: NumberLiteral
}
export function createI32NumberType(literal?: NumberLiteral): I32NumberType {
return {
$type: 'i32',
literal,
}
}
export function isI32NumberType(item: TypeDescription): item is I32NumberType {
return item.$type === 'i32'
}
// f32
export interface F32NumberType {
readonly $type: 'f32'
readonly literal?: NumberLiteral
}
export function createF32NumberType(literal?: NumberLiteral): F32NumberType {
return {
$type: 'f32',
literal,
}
}
export function isF32NumberType(item: TypeDescription): item is F32NumberType {
return item.$type === 'f32'
}
// f64
export interface F64NumberType {
readonly $type: 'f64'
readonly literal?: NumberLiteral
}
export function createF64NumberType(literal?: NumberLiteral): F64NumberType {
return {
$type: 'f64',
literal,
}
}
export function isF64NumberType(item: TypeDescription): item is F64NumberType {
return item.$type === 'f64'
}
// type
export interface TypeDeclaration {
readonly $type: 'type'
readonly name?: Identifier
readonly value?: TypeExpression
}
export function createTypeDeclaration(name: Identifier, value: TypeExpression): TypeDeclaration {
return {
$type: 'type',
name,
value,
}
}
export function isTypeDeclaration(item: TypeDeclaration): item is TypeDeclaration {
return item.$type === 'type'
}
// function
export interface FunctionType {
readonly $type: 'function'
readonly returnType: TypeDescription
readonly parameters: FunctionTypeParameter[]
}
export interface FunctionTypeParameter {
name: string
type: TypeDescription
}
// export function createFunctionType(func: ClassicFunction): FunctionType {
// const returnType: TypeDescription
// const parameters: FunctionParameter[]
export function createFunctionType(parameters: FunctionTypeParameter[], returnType: TypeDescription): FunctionType {
return {
$type: 'function',
parameters,
returnType,
}
}
export function isFunctionType(item: TypeDescription): item is FunctionType {
return item.$type === 'function'
}
// error
export interface TypeInferenceError {
readonly $type: 'error'
readonly source?: AstNode
readonly message: string
}
export function createTypeInferenceError(message: string, source?: AstNode): TypeInferenceError {
return {
$type: 'error',
message,
source,
}
}
export function isTypeInferenceError(item: TypeDescription): item is TypeInferenceError {
return item.$type === 'error'
}
export function typeToString(item: TypeDescription): string {
if (isFunctionType(item)) {
const params = item.parameters.map(e => `${e.name}: ${typeToString(e.type)}`).join(', ')
return `(${params}) => ${typeToString(item.returnType)}`
} else {
return item.$type
}
}