-
Notifications
You must be signed in to change notification settings - Fork 547
/
function2.go
108 lines (87 loc) · 2.23 KB
/
function2.go
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
package qlang
import (
"qiniupkg.com/text/tpl.v1/interpreter.util"
"qlang.io/exec"
)
// -----------------------------------------------------------------------------
func (p *Compiler) function(e interpreter.Engine) {
fnb, _ := p.gstk.Pop()
variadic := p.popArity()
arity := p.popArity()
args := p.gstk.PopFnArgs(arity)
instr := p.code.Reserve()
fnctx := p.fnctx
p.exits = append(p.exits, func() {
start, end, symtbl := p.clFunc(e, "doc", fnb, fnctx, args)
instr.Set(exec.Func(nil, start, end, symtbl, args, variadic != 0))
})
}
func (p *Compiler) anonymFn(e interpreter.Engine) {
fnb, _ := p.gstk.Pop()
instr := p.code.Reserve()
fnctx := p.fnctx
p.exits = append(p.exits, func() {
start, end, symtbl := p.clFunc(e, "doc", fnb, fnctx, nil)
instr.Set(exec.AnonymFn(start, end, symtbl))
})
}
func (p *Compiler) fnReturn(e interpreter.Engine) {
arity := p.popArity()
p.code.Block(exec.Return(arity))
}
// Done completes all exit functions generated by `Cl`.
//
func (p *Compiler) Done() {
for {
n := len(p.exits)
if n == 0 {
break
}
onExit := p.exits[n-1]
p.exits = p.exits[:n-1]
onExit()
}
}
func (p *Compiler) fnDefer(e interpreter.Engine) {
src, _ := p.gstk.Pop()
instr := p.code.Reserve()
fnctx := p.fnctx
p.exits = append(p.exits, func() {
start, end := p.clBlock(e, "expr", src, fnctx)
p.codeLine(src)
instr.Set(exec.Defer(start, end))
})
}
func (p *Compiler) fnRecover() {
p.code.Block(exec.Recover)
}
func (p *Compiler) clFunc(
e interpreter.Engine, g string, src interface{},
parent *funcCtx, args []string) (start, end int, symtbl map[string]int) {
ctx := newFuncCtx(parent, args)
old := p.fnctx
p.fnctx = ctx
start, end = p.cl(e, g, src)
symtbl = ctx.symtbl
p.fnctx = old
return
}
func (p *Compiler) clBlock(
e interpreter.Engine, g string, src interface{}, parent *funcCtx) (start, end int) {
old := p.fnctx
p.fnctx = parent
start, end = p.cl(e, g, src)
p.fnctx = old
return
}
func (p *Compiler) cl(e interpreter.Engine, g string, src interface{}) (start, end int) {
start = p.code.Len()
if src != nil {
if err := e.EvalCode(p, g, src); err != nil {
panic(err)
}
}
end = p.code.Len()
return
}
// -----------------------------------------------------------------------------