1
0
Fork 0

Migrate Sirupsen to sirupsen.

This commit is contained in:
Ludovic Fernandez 2018-01-22 12:16:03 +01:00 committed by Traefiker
parent c134dcd6fe
commit fb4ba7af2b
684 changed files with 92394 additions and 33943 deletions

View file

@ -7,6 +7,9 @@ import (
"go/token"
"reflect"
"strconv"
"strings"
"github.com/gravitational/trace"
)
func NewParser(d Def) (Parser, error) {
@ -49,7 +52,7 @@ func (p *predicateParser) parseNode(node ast.Node) (interface{}, error) {
if err != nil {
return nil, err
}
arguments, err := collectLiterals(n.Args)
arguments, err := p.evaluateArguments(n.Args)
if err != nil {
return nil, err
}
@ -57,13 +60,92 @@ func (p *predicateParser) parseNode(node ast.Node) (interface{}, error) {
case *ast.ParenExpr:
return p.parseNode(n.X)
}
return nil, fmt.Errorf("unsupported %T", node)
return nil, trace.BadParameter("unsupported %T", node)
}
func (p *predicateParser) evaluateArguments(nodes []ast.Expr) ([]interface{}, error) {
out := make([]interface{}, len(nodes))
for i, n := range nodes {
val, err := p.evaluateExpr(n)
if err != nil {
return nil, trace.Wrap(err)
}
out[i] = val
}
return out, nil
}
func (p *predicateParser) evaluateExpr(n ast.Expr) (interface{}, error) {
switch l := n.(type) {
case *ast.BasicLit:
val, err := literalToValue(l)
if err != nil {
return nil, err
}
return val, nil
case *ast.IndexExpr:
if p.d.GetProperty == nil {
return nil, trace.NotFound("properties are not supported")
}
mapVal, err := p.evaluateExpr(l.X)
if err != nil {
return nil, trace.Wrap(err)
}
keyVal, err := p.evaluateExpr(l.Index)
if err != nil {
return nil, trace.Wrap(err)
}
val, err := p.d.GetProperty(mapVal, keyVal)
if err != nil {
return nil, trace.Wrap(err)
}
return val, nil
case *ast.SelectorExpr:
fields, err := evaluateSelector(l, []string{})
if err != nil {
return nil, trace.Wrap(err)
}
if p.d.GetIdentifier == nil {
return nil, trace.NotFound("%v is not defined", strings.Join(fields, "."))
}
val, err := p.d.GetIdentifier(fields)
if err != nil {
return nil, trace.Wrap(err)
}
return val, nil
case *ast.Ident:
if p.d.GetIdentifier == nil {
return nil, trace.NotFound("%v is not defined", l.Name)
}
val, err := p.d.GetIdentifier([]string{l.Name})
if err != nil {
return nil, trace.Wrap(err)
}
return val, nil
default:
return nil, trace.BadParameter("%T is not supported", n)
}
}
// evaluateSelector recursively evaluates the selector field and returns a list
// of properties at the end
func evaluateSelector(sel *ast.SelectorExpr, fields []string) ([]string, error) {
fields = append([]string{sel.Sel.Name}, fields...)
switch l := sel.X.(type) {
case *ast.SelectorExpr:
return evaluateSelector(l, fields)
case *ast.Ident:
fields = append([]string{l.Name}, fields...)
return fields, nil
default:
return nil, trace.BadParameter("unsupported selector type: %T", l)
}
}
func (p *predicateParser) getFunction(name string) (interface{}, error) {
v, ok := p.d.Functions[name]
if !ok {
return nil, fmt.Errorf("unsupported function: %s", name)
return nil, trace.BadParameter("unsupported function: %s", name)
}
return v, nil
}
@ -97,7 +179,7 @@ func (p *predicateParser) getJoinFunction(op token.Token) (interface{}, error) {
fn = p.d.Operators.NEQ
}
if fn == nil {
return nil, fmt.Errorf("%v is not supported", op)
return nil, trace.BadParameter("%v is not supported", op)
}
return fn, nil
}
@ -107,62 +189,46 @@ func getIdentifier(node ast.Node) (string, error) {
if ok {
id, ok := sexpr.X.(*ast.Ident)
if !ok {
return "", fmt.Errorf("expected selector identifier, got: %T", sexpr.X)
return "", trace.BadParameter("expected selector identifier, got: %T", sexpr.X)
}
return fmt.Sprintf("%s.%s", id.Name, sexpr.Sel.Name), nil
}
id, ok := node.(*ast.Ident)
if !ok {
return "", fmt.Errorf("expected identifier, got: %T", node)
return "", trace.BadParameter("expected identifier, got: %T", node)
}
return id.Name, nil
}
func collectLiterals(nodes []ast.Expr) ([]interface{}, error) {
out := make([]interface{}, len(nodes))
for i, n := range nodes {
l, ok := n.(*ast.BasicLit)
if !ok {
return nil, fmt.Errorf("expected literal, got %T", n)
}
val, err := literalToValue(l)
if err != nil {
return nil, err
}
out[i] = val
}
return out, nil
}
func literalToValue(a *ast.BasicLit) (interface{}, error) {
switch a.Kind {
case token.FLOAT:
value, err := strconv.ParseFloat(a.Value, 64)
if err != nil {
return nil, fmt.Errorf("failed to parse argument: %s, error: %s", a.Value, err)
return nil, trace.BadParameter("failed to parse argument: %s, error: %s", a.Value, err)
}
return value, nil
case token.INT:
value, err := strconv.Atoi(a.Value)
if err != nil {
return nil, fmt.Errorf("failed to parse argument: %s, error: %s", a.Value, err)
return nil, trace.BadParameter("failed to parse argument: %s, error: %s", a.Value, err)
}
return value, nil
case token.STRING:
value, err := strconv.Unquote(a.Value)
if err != nil {
return nil, fmt.Errorf("failed to parse argument: %s, error: %s", a.Value, err)
return nil, trace.BadParameter("failed to parse argument: %s, error: %s", a.Value, err)
}
return value, nil
}
return nil, fmt.Errorf("unsupported function argument type: '%v'", a.Kind)
return nil, trace.BadParameter("unsupported function argument type: '%v'", a.Kind)
}
func callFunction(f interface{}, args []interface{}) (v interface{}, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("%s", r)
err = trace.BadParameter("%s", r)
}
}()
arguments := make([]reflect.Value, len(args))
@ -182,9 +248,9 @@ func callFunction(f interface{}, args []interface{}) (v interface{}, err error)
}
err, ok := e.(error)
if !ok {
return nil, fmt.Errorf("expected error as a second return value, got %T", e)
return nil, trace.BadParameter("expected error as a second return value, got %T", e)
}
return v, err
}
return nil, fmt.Errorf("expected at least one return argument for '%v'", fn)
return nil, trace.BadParameter("expected at least one return argument for '%v'", fn)
}