forked from japm/goScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhelpers.go
More file actions
114 lines (103 loc) · 2.47 KB
/
Copy pathhelpers.go
File metadata and controls
114 lines (103 loc) · 2.47 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
107
108
109
110
111
112
113
114
//Package goScript, javascript Eval() for go
//The MIT License (MIT)
//Copyright (c) 2016 Juan Pascual
package goScript
import (
"fmt"
"go/ast"
//"reflect"
//"time"
)
func isEmpty(s string) bool {
if len(s) == 0 {
return true
}
for _, c := range s {
if c != ' ' && c != '\t' {
return false
}
}
return true
}
//AST structires with values resolved for constants
//specialized by each expression
type constNodeBasicLit struct {
ast.BasicLit
value interface{}
}
type constNodeIdent struct {
ast.Ident
value interface{}
}
type constNodeUnaryExpr struct {
ast.UnaryExpr
value interface{}
}
type constNodeBinaryExpr struct {
ast.BinaryExpr
value interface{}
}
type constNodeParenExpr struct {
ast.ParenExpr
value interface{}
}
//Replace constants in expressions for its values precalculated
//using AST nodes with values.
func resolveConstants(expr ast.Node) ast.Node {
switch expr.(type) {
case *ast.BasicLit:
v, e := evalBasicLit(expr.(*ast.BasicLit), nil)
if e != nil {
return expr
}
return &constNodeBasicLit{*expr.(*ast.BasicLit), v}
case *ast.BinaryExpr:
bexp := expr.(*ast.BinaryExpr)
bexp.X = resolveConstants(bexp.X).(ast.Expr)
bexp.Y = resolveConstants(bexp.Y).(ast.Expr)
v, e := evalBinaryExpr(expr.(*ast.BinaryExpr), nilContext{})
if e != nil {
return expr
}
return &constNodeBinaryExpr{*expr.(*ast.BinaryExpr), v}
case *ast.ParenExpr:
pexp := expr.(*ast.ParenExpr)
pexp.X = resolveConstants(pexp.X).(ast.Expr)
v, e := eval(pexp.X, nilContext{})
if e != nil {
return expr
}
return &constNodeParenExpr{*expr.(*ast.ParenExpr), v}
case *ast.Ident:
v, e := evalIdent(expr.(*ast.Ident), nilContext{})
if e != nil {
return expr
}
return &constNodeIdent{*expr.(*ast.Ident), v}
case *ast.UnaryExpr:
v, e := evalUnaryExpr(expr.(*ast.UnaryExpr), nilContext{})
if e != nil {
fmt.Println(e)
return expr
}
return &constNodeUnaryExpr{*expr.(*ast.UnaryExpr), v}
case *ast.CallExpr:
callexp := expr.(*ast.CallExpr)
for key, value := range callexp.Args {
callexp.Args[key] = resolveConstants(value).(ast.Expr)
}
return expr
case *ast.IndexExpr:
idexpr := expr.(*ast.IndexExpr)
idexpr.Index = resolveConstants(idexpr.Index).(ast.Expr)
return expr
case *ast.SliceExpr:
slexpr := expr.(*ast.SliceExpr)
slexpr.Low = resolveConstants(slexpr.Low).(ast.Expr)
slexpr.High = resolveConstants(slexpr.High).(ast.Expr)
slexpr.X = resolveConstants(slexpr.X).(ast.Expr)
return expr
default:
return expr
}
}