-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathcompiler.js
63 lines (55 loc) · 1.56 KB
/
compiler.js
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
import { parseExpression, parseCode } from './parser'
const expressionCache = new Map()
const codeCache = new Map()
export function compileExpression (src) {
if (typeof src !== 'string') {
throw new TypeError('First argument must be a string.')
}
let expression = expressionCache.get(src)
if (!expression) {
expression = parseExpression(src)
expressionCache.set(src, expression)
}
if (typeof expression === 'function') {
return expression
}
return function evaluateExpression (context, tempVars) {
let value = expression.exec(context, tempVars)
for (let filter of expression.filters) {
const args = filter.argExpressions.map(evaluateArgExpression, context)
value = filter.effect(value, ...args)
}
return value
}
}
export function compileCode (src) {
if (typeof src !== 'string') {
throw new TypeError('First argument must be a string.')
}
let code = codeCache.get(src)
if (!code) {
code = parseCode(src)
codeCache.set(src, code)
}
if (typeof code === 'function') {
return code
}
const context = {}
return function evaluateCode (state, tempVars) {
let i = 0
function next () {
Object.assign(context, tempVars)
if (i < code.limiters.length) {
const limiter = code.limiters[i++]
const args = limiter.argExpressions.map(evaluateArgExpression, state)
limiter.effect(next, context, ...args)
} else {
code.exec(state, tempVars)
}
}
next()
}
}
function evaluateArgExpression (argExpression) {
return argExpression(this)
}