-
Notifications
You must be signed in to change notification settings - Fork 546
/
class2.go
111 lines (90 loc) · 2.21 KB
/
class2.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
109
110
111
package qlang
import (
"errors"
ipt "qiniupkg.com/text/tpl.v1/interpreter"
"qiniupkg.com/text/tpl.v1/interpreter.util"
"qlang.io/exec"
)
// -----------------------------------------------------------------------------
type functionInfo struct {
args []string // args[0] => function name
fnb interface{}
variadic bool
}
// -----------------------------------------------------------------------------
func (p *Compiler) memberFuncDecl() {
fnb, _ := p.gstk.Pop()
variadic := p.popArity()
arity := p.popArity()
args := p.gstk.PopFnArgs(arity + 1)
fn := &functionInfo{
args: args,
fnb: fnb,
variadic: variadic != 0,
}
p.gstk.Push(fn)
}
func (p *Compiler) addMethods(cls *exec.Class, e interpreter.Engine, parent *funcCtx, members []interface{}) {
for _, val := range members {
v := val.(*functionInfo)
name := v.args[0]
v.args[0] = "this"
start, end, symtbl := p.clFunc(e, "doc", v.fnb, parent, v.args)
fn := exec.NewFunction(cls, start, end, symtbl, v.args, v.variadic)
fn.Parent = cls.Ctx
cls.Fns[name] = fn
}
}
func (p *Compiler) fnClass(e interpreter.Engine) {
arity := p.popArity()
members := p.gstk.PopNArgs(arity)
instr := p.code.Reserve()
fnctx := p.fnctx
p.exits = append(p.exits, func() {
cls := exec.IClass()
p.addMethods(cls, e, fnctx, members)
instr.Set(cls)
})
}
// InjectMethods injects some methods into a class.
//
func (p *Compiler) InjectMethods(cls *exec.Class, code []byte) (err error) {
defer func() {
if e := recover(); e != nil {
switch v := e.(type) {
case string:
err = errors.New(v)
case error:
err = v
default:
panic(e)
}
}
}()
engine, err := ipt.New(p, p.Opts)
if err != nil {
return
}
p.ipt = engine
src, err := engine.Tokenize(code, "")
if err != nil {
return
}
p.cl(engine, "methods", src)
arity := p.popArity()
members := p.gstk.PopNArgs(arity)
p.addMethods(cls, engine, p.fnctx, members)
p.Done()
return
}
func (p *Compiler) fnNew() {
nArgs := p.popArity()
if nArgs != 0 {
nArgs = p.popArity()
}
p.code.Block(exec.INew(nArgs))
}
func (p *Compiler) memberRef(name string) {
p.code.Block(exec.MemberRef(name))
}
// -----------------------------------------------------------------------------