-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharrow.go
109 lines (101 loc) · 1.9 KB
/
arrow.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
package main
import (
"fmt"
"github.com/tdewolff/parse/v2/js"
)
type convertArrow struct {
parent js.INode
scope *js.Scope
block *js.BlockStmt
}
func ConvertArrow(ast *js.AST) {
js.Walk(convertArrow{}, ast)
}
func (c convertArrow) Enter(n js.INode) js.IVisitor {
switch v := n.(type) {
case *js.ArrowFunc:
f := &js.FuncDecl{
Async: v.Async,
Params: v.Params,
Body: v.Body,
}
that := AddThat(c.block, c.scope)
ft := BindThat(f, that)
switch vv := c.parent.(type) {
case *js.Arg:
vv.Value = ft.(js.IExpr)
case *js.BindingElement:
vv.Default = ft.(js.IExpr)
case *js.GroupExpr:
vv.X = ft.(js.IExpr)
case *js.Property:
vv.Value = ft.(js.IExpr)
default:
panic(fmt.Sprintf("unknown parent %T", c.parent))
}
}
if blk, ok := n.(*js.BlockStmt); ok {
c.block = blk
c.scope = &blk.Scope
}
c.parent = n
return c
}
func (c convertArrow) Exit(n js.INode) {}
func BindThat(f *js.FuncDecl, that *js.Var) js.INode {
bind := &js.DotExpr{
X: f,
Y: js.LiteralExpr{
Data: []byte("bind"),
},
}
c := &js.CallExpr{
X: bind,
Args: js.Args{
List: []js.Arg{
js.Arg{
Value: that,
},
},
},
}
return c
}
func getThat(blk *js.BlockStmt) (that *js.Var, ok bool) {
for _, st := range blk.List {
d, ok := st.(*js.VarDecl)
if !ok {
continue
}
if be := d.List[0]; string(be.Default.String()) == "this" {
v, ok := be.Binding.(*js.Var)
if ok {
return v, true
}
}
}
return
}
func AddThat(blk *js.BlockStmt, scope *js.Scope) (that *js.Var) {
if that, ok := getThat(blk); ok {
return that
}
that = &js.Var{
Decl: js.VariableDecl,
Data: []byte("that$" + unique()),
}
d := &js.VarDecl{
TokenType: js.VarToken,
List: []js.BindingElement{
js.BindingElement{
Default: &js.LiteralExpr{
Data: []byte("this"),
},
Binding: that,
},
},
Scope: scope,
}
blk.List = append([]js.IStmt{d}, blk.List...)
return
}