-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompute.ts
More file actions
106 lines (75 loc) · 2.78 KB
/
compute.ts
File metadata and controls
106 lines (75 loc) · 2.78 KB
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
import { Token, TokenType, match } from './token'
export class ComputedType {
name = 'Unkown'
}
class Integer extends ComputedType {
name = 'Integer'
}
class Float extends ComputedType {
name = 'Float'
}
class Void extends ComputedType {
name = 'Void'
}
let nameTable: { [key: string]: ComputedType } = {}
type ValidationError = {
message: string,
lines: number[],
character: number[]
}
const validationRules: Map<TokenType, (token: Token) => ValidationError | null> = new Map()
const computeRules: Map<TokenType, (token: Token) => void> = new Map()
validationRules.set(TokenType.Definition, token => null)
computeRules.set(TokenType.Definition, token => {
computeToken(token.content.value)
computeToken(token.content.type)
token.computedType = new Void()
nameTable[token.content.name.content] = token.content.type.computedType
})
validationRules.set(TokenType.FunctionDefinition, token => null)
computeRules.set(TokenType.FunctionDefinition, token => {
const namesOutsideOfScope = Object.keys(nameTable)
computeToken(token.content.type)
for(const childToken of token.content.value) {
computeToken(childToken)
}
token.computedType = new Void()
for(const name of Object.keys(nameTable)) {
if(namesOutsideOfScope.includes(name)) continue
delete nameTable[name]
}
})
validationRules.set(TokenType.Assignment, token => null)
computeRules.set(TokenType.Assignment, token => {
computeToken(token.content.value)
token.computedType = new Void()
})
validationRules.set(TokenType.Literal, token => null)
computeRules.set(TokenType.Literal, token => {
if(/^[0-9]+$/.test(token.content)) {
token.computedType = new Integer()
return
}
})
validationRules.set(TokenType.Type, token => null)
computeRules.set(TokenType.Type, token => {
if(match(token, 'float', TokenType.Type)) token.computedType = new Float()
if(match(token, 'int', TokenType.Type)) token.computedType = new Integer()
if(match(token, 'void', TokenType.Type)) token.computedType = new Void()
})
function computeToken(token: Token) {
const validationRule = validationRules.get(token.tokenType)
if(validationRule === undefined) return
let validationError = validationRule(token)
if(validationError !== null) throw new Error(validationError.message)
const computeRule = computeRules.get(token.tokenType)
if(computeRule === undefined) return
computeRule(token)
}
export function compute(tree: Token[], sourceExportedNames: { [key: string]: { [key: string]: ComputedType } }): { tree: Token[], exportedNames: { [key: string]: ComputedType } } {
nameTable = {}
for(const token of tree) {
computeToken(token)
}
return { tree: tree, exportedNames: {} }
}