expressions

package module
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2024 License: Apache-2.0 Imports: 7 Imported by: 1

README

Arcaflow Expressions Library

This library provides the ability to parse Arcaflow expressions.

Installation

This library can be installed as a Go module dependency:

go get go.flow.arcalot.io/expressions

Evaluating expressions

You can evaluate expressions against a data set consisting of primitive types (bool, int, float, string, map, slice) by parsing the expression and then calling the Evaluate() function:

package main

import (
    "fmt"
    "log"

    "go.flow.arcalot.io/expressions"
)

func main() {
    expr, err := expressions.New("$.foo.bar")
    if err != nil {
        log.Fatal(err)
    }
    result, err := expr.Evaluate(
        // Pass the data here:
        map[string]any{
            "foo": map[string]any{
                "bar": "hello world!",
            },
        },
        // Pass the workflow context (map of file names to content) here:
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(result)
}

Building a dependency tree

Similarly, you can also evaluate an expression against a scope and get a list of dependencies an expression has:

package main

import (
    "fmt"

    "go.flow.arcalot.io/expressions"
    "go.flow.arcalot.io/pluginsdk/schema"
)

var myScope = schema.NewScopeSchema(
    schema.NewObjectSchema(
        "root",
        map[string]*schema.PropertySchema{
            "foo": schema.NewPropertySchema(
                schema.NewStringSchema(nil, nil, nil),
                nil,
                true,
                nil,
                nil,
                nil,
                nil,
                nil,
            ),
        },
    ),
)

func main() {
    expr, err := expressions.New("$.foo")
    if err != nil {
        panic(err)
    }

    dependencyList, err := expr.Dependencies(
        myScope,
        nil,
    )
    if err != nil {
        panic(err)
    }

    fmt.Printf("%v", dependencyList)
    // Output: [$.foo]
}

Evaluating result types

You can also evaluate an expression and retrieve the result type. Note, that the result is not 100% guaranteed as the result may be optional and the value may not be available.

package main

import (
    "fmt"

    "go.flow.arcalot.io/expressions"
    "go.flow.arcalot.io/pluginsdk/schema"
)

var scopeForType = schema.NewScopeSchema(
    schema.NewObjectSchema(
        "root",
        map[string]*schema.PropertySchema{
            "foo": schema.NewPropertySchema(
                schema.NewStringSchema(nil, nil, nil),
                nil,
                true,
                nil,
                nil,
                nil,
                nil,
                nil,
            ),
        },
    ),
)

func main() {
    expr, err := expressions.New("$.foo")
    if err != nil {
        panic(err)
    }

    t, err := expr.Type(
        scopeForType,
        nil,
    )
    if err != nil {
        panic(err)
    }

    fmt.Printf("%v", t.TypeID())
    // Output: string
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Expression

type Expression interface {
	// Type evaluates the expression and evaluates the type on the specified schema.
	Type(schema schema.Scope, functions map[string]schema.Function, workflowContext map[string][]byte) (schema.Type, error)
	// Dependencies traverses the passed scope and evaluates the items this expression depends on. This is useful to
	// construct a dependency tree based on expressions.
	// Returns the path to the object in the schema that it depends on, or nil if it's a literal that doesn't depend
	// on it.
	// unpackRequirements specifies which paths to include, and which values to include in paths.
	Dependencies(schema schema.Type, functions map[string]schema.Function, workflowContext map[string][]byte, unpackRequirements UnpackRequirements) ([]Path, error)
	// Evaluate evaluates the expression on the given data set regardless of any
	// schema. The caller is responsible for validating the expected schema.
	Evaluate(data any, functions map[string]schema.CallableFunction, workflowContext map[string][]byte) (any, error)
	// String returns the string representation of the expression.
	String() string
}

Expression is an interface describing how expressions should behave.

func New

func New(expressionString string) (Expression, error)

New parses the specified expression and returns the expression structure.

type Path

type Path []any

Path describes the path needed to take to reach an item. Items can either be strings or integers.

func (Path) String

func (p Path) String() string

String returns the dot-concatenated string version of the path as an Arcaflow-expression.

type PathNodeType added in v0.3.0

type PathNodeType string
const (
	// DataRootNode is a node describing the root data path '$'
	// The valid PathItem for this node type is '$'
	DataRootNode PathNodeType = "root"
	// FunctionNode is a node describing a function access. It is a type of root node.
	// The valid PathItems for this node type are function name strings.
	FunctionNode PathNodeType = "function"
	// AccessNode is accessing a field within the object preceding it.
	// Valid PathItems for this node type are object field names strings.
	AccessNode PathNodeType = "access"
	// KeyNode means that it's a node that describes the access to the node preceding it. It could be describing
	// an integer literal index, or a string literal map key. This info is useful in the cases where the index or
	// map key can change the dependency.
	// Valid PathItems for this node type are integers for indexes, or strings or integers for map accesses.
	KeyNode PathNodeType = "key"
	// PastTerminalNode refers to a value access that is past a terminal value. An any type is a terminal value.
	// This node type means it's trying to access a value within an any type.
	// Valid PathItems for this node type are object field names strings.
	PastTerminalNode PathNodeType = "past-terminal"
)

type PathTree

type PathTree struct {
	// The value at the part of the tree
	PathItem any
	NodeType PathNodeType
	Subtrees []*PathTree
}

PathTree holds multiple paths in a branching fashion.

func (PathTree) Unpack

func (p PathTree) Unpack(requirements UnpackRequirements) []Path

Unpack unpacks the path tree into a list of paths.

type SupportedNumber added in v0.3.0

type SupportedNumber interface {
	int64 | float64
}

type UnpackRequirements added in v0.3.0

type UnpackRequirements struct {
	ExcludeDataRootPaths     bool // Exclude paths that start at data root
	ExcludeFunctionRootPaths bool // Exclude paths that start at a function
	StopAtTerminals          bool // Whether to stop at terminals (any types are terminals).
	IncludeKeys              bool // Whether to include the keys in the path. // Example, the 0 in `$ -> list -> 0 -> a`
}

Directories

Path Synopsis
internal
ast
Package ast is designed to tokenizer and parse jsonpath expressions.
Package ast is designed to tokenizer and parse jsonpath expressions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL