func (v *TypeCheck) Visit(root ast.Node) error { v.lock.Lock() defer v.lock.Unlock() defer v.reset() root.Accept(v.visit) return v.err }
func (v *evalVisitor) Visit(root ast.Node) (interface{}, ast.Type, error) { // Run the actual visitor pattern root.Accept(v.visit) // Get our result and clear out everything else var result *ast.LiteralNode if v.Stack.Len() > 0 { result = v.Stack.Pop().(*ast.LiteralNode) } else { result = new(ast.LiteralNode) } resultErr := v.err if resultErr == errExitUnknown { // This means the return value is unknown and we used the error // as an early exit mechanism. Reset since the value on the stack // should be the unknown value. resultErr = nil } // Clear everything else so we aren't just dangling v.Stack.Reset() v.err = nil t, err := result.Type(v.Scope) if err != nil { return nil, ast.TypeInvalid, err } return result.Value, t, resultErr }
// DetectVariables takes an AST root and returns all the interpolated // variables that are detected in the AST tree. func DetectVariables(root ast.Node) ([]InterpolatedVariable, error) { var result []InterpolatedVariable var resultErr error // Visitor callback fn := func(n ast.Node) ast.Node { if resultErr != nil { return n } vn, ok := n.(*ast.VariableAccess) if !ok { return n } v, err := NewInterpolatedVariable(vn.Name) if err != nil { resultErr = err return n } result = append(result, v) return n } // Visitor pattern root.Accept(fn) if resultErr != nil { return nil, resultErr } return result, nil }
func (c *IdentifierCheck) Visit(root ast.Node) error { c.lock.Lock() defer c.lock.Unlock() defer c.reset() root.Accept(c.visit) return c.err }
func (v *TypeCheck) Visit(root ast.Node) error { v.lock.Lock() defer v.lock.Unlock() defer v.reset() root.Accept(v.visit) // If the resulting type is unknown, then just let the whole thing go. if v.err == errExitUnknown { v.err = nil } return v.err }
// DetectVariables takes an AST root and returns all the interpolated // variables that are detected in the AST tree. func DetectVariables(root ast.Node) ([]InterpolatedVariable, error) { var result []InterpolatedVariable var resultErr error // Visitor callback fn := func(n ast.Node) ast.Node { if resultErr != nil { return n } switch vn := n.(type) { case *ast.VariableAccess: v, err := NewInterpolatedVariable(vn.Name) if err != nil { resultErr = err return n } result = append(result, v) case *ast.Index: if va, ok := vn.Target.(*ast.VariableAccess); ok { v, err := NewInterpolatedVariable(va.Name) if err != nil { resultErr = err return n } result = append(result, v) } if va, ok := vn.Key.(*ast.VariableAccess); ok { v, err := NewInterpolatedVariable(va.Name) if err != nil { resultErr = err return n } result = append(result, v) } default: return n } return n } // Visitor pattern root.Accept(fn) if resultErr != nil { return nil, resultErr } return result, nil }
func (v *evalVisitor) Visit(root ast.Node) (interface{}, ast.Type, error) { // Run the actual visitor pattern root.Accept(v.visit) // Get our result and clear out everything else var result *ast.LiteralNode if v.Stack.Len() > 0 { result = v.Stack.Pop().(*ast.LiteralNode) } else { result = new(ast.LiteralNode) } resultErr := v.err // Clear everything else so we aren't just dangling v.Stack.Reset() v.err = nil t, err := result.Type(v.Scope) if err != nil { return nil, ast.TypeInvalid, err } return result.Value, t, resultErr }