func evalTypeDeclaration(node *ast.TypeDeclarationNode, scope *stateful.Scope, predefinedVars, defaultVars map[string]Var, ignoreMissingVars bool) error { var actualType ast.ValueType switch node.Type.Ident { case "int": actualType = ast.TInt case "float": actualType = ast.TFloat case "bool": actualType = ast.TBool case "string": actualType = ast.TString case "regex": actualType = ast.TRegex case "duration": actualType = ast.TDuration case "lambda": actualType = ast.TLambda case "list": actualType = ast.TList case "star": actualType = ast.TStar default: return fmt.Errorf("invalid var type %q", node.Type.Ident) } name := node.Node.Ident desc := "" if node.Comment != nil { desc = node.Comment.CommentString() } defaultVars[name] = Var{ Type: actualType, Value: nil, Description: desc, } if predefinedValue, ok := predefinedVars[name]; ok { if predefinedValue.Type != actualType { return fmt.Errorf("invalid type supplied for %s, got %v exp %v", name, predefinedValue.Type, actualType) } v, err := convertVarToValue(Var{Value: predefinedValue.Value, Type: actualType}) if err != nil { return err } scope.Set(name, v) } else if ignoreMissingVars { // Set zero value on scope, so execution can continue scope.Set(name, ast.ZeroValue(actualType)) } else { return fmt.Errorf("missing value for var %q.", name) } return nil }
func createPipelineAndVars( script string, sourceEdge EdgeType, scope *stateful.Scope, deadman DeadmanService, predefinedVars map[string]tick.Var, ignoreMissingVars bool, ) (*Pipeline, map[string]tick.Var, error) { p := &Pipeline{ deadman: deadman, } var src Node switch sourceEdge { case StreamEdge: src = newStreamNode() scope.Set("stream", src) case BatchEdge: src = newBatchNode() scope.Set("batch", src) default: return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge) } p.addSource(src) vars, err := tick.Evaluate(script, scope, predefinedVars, ignoreMissingVars) if err != nil { return nil, nil, err } if deadman.Global() { switch s := src.(type) { case *StreamNode: s.Deadman(deadman.Threshold(), deadman.Interval()) case *BatchNode: s.Deadman(deadman.Threshold(), deadman.Interval()) default: return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge) } } if err = p.Walk( func(n Node) error { return n.validate() }); err != nil { return nil, nil, err } return p, vars, nil }
func evalDeclaration(node *ast.DeclarationNode, scope *stateful.Scope, stck *stack, predefinedVars, defaultVars map[string]Var) error { name := node.Left.Ident if v, _ := scope.Get(name); v != nil { return fmt.Errorf("attempted to redefine %s, vars are immutable", name) } value := stck.Pop() if i, ok := value.(*ast.IdentifierNode); ok { // Resolve identifier v, err := scope.Get(i.Ident) if err != nil { return err } value = v } actualType := ast.TypeOf(value) // Populate set of default vars if actualType != ast.InvalidType { desc := "" if node.Comment != nil { desc = node.Comment.CommentString() } v, err := convertValueToVar(value, actualType, desc) if err != nil { return err } defaultVars[name] = v } // Populate scope, first check for predefined var if predefinedValue, ok := predefinedVars[name]; ok { if predefinedValue.Type != actualType { return fmt.Errorf("invalid type supplied for %s, got %v exp %v", name, predefinedValue.Type, actualType) } v, err := convertVarToValue(Var{Value: predefinedValue.Value, Type: actualType}) if err != nil { return err } value = v } scope.Set(name, value) return nil }
// fillScope - given a scope and reference variables, we fill the exact variables from the now, fields and tags. func fillScope(vars *stateful.Scope, referenceVariables []string, now time.Time, fields models.Fields, tags models.Tags) error { for _, refVariableName := range referenceVariables { if refVariableName == "time" { vars.Set("time", now.Local()) continue } // Support the error with tags/fields collision var fieldValue interface{} var isFieldExists bool var tagValue interface{} var isTagExists bool if fieldValue, isFieldExists = fields[refVariableName]; isFieldExists { vars.Set(refVariableName, fieldValue) } if tagValue, isTagExists = tags[refVariableName]; isTagExists { if isFieldExists { return fmt.Errorf("cannot have field and tags with same name %q", refVariableName) } vars.Set(refVariableName, tagValue) } if !isFieldExists && !isTagExists { if !vars.Has(refVariableName) { return fmt.Errorf("no field or tag exists for %s", refVariableName) } } } return nil }