core

package
v0.2.6 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2026 License: GPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package core provides built-in functions for the CSV spreadsheet language

Index

Constants

This section is empty.

Variables

View Source
var DispatchMap dispatchMap = dispatchMap{
	"EXEC": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "EXEC(command:string, args:string...):string"
		return Exec(format, call, values...)
	},

	"SUM": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "SUM(values:number...):number"
		guard := MakeSameTypeGuard(format, ast.IsNumeric)
		return callNumbersFunction(format, sum, sum, guard, call, values...)
	},

	"ADD": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ADD(a:number, b:number):number"
		guard := MakeArityGuard(format, 2)
		return callNumbersFunction(format, sum, sum, guard, call, values...)
	},

	"PRODUCT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return callNumbersFunction(
			"PRODUCT(values:number...):number",
			product,
			product,
			EmptyGuard,
			call,
			values...,
		)
	},

	"AVERAGE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return callNumbersFunction(
			"AVERAGE(values:number...):number",
			average,
			average,
			EmptyGuard,
			call,
			values...,
		)
	},

	"MAX": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return callNumbersFunction(
			"MAX(values:number...):number",
			max,
			max,
			EmptyGuard,
			call,
			values...,
		)
	},

	"MAXA": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		converted, failed := parseStringExpressions(call, values)
		if failed != nil {
			return nil, ErrUnsupportedArgument("MAXA(values:number|string...):number",
				call, failed)
		}
		return callNumbersFunction(
			"MAXA(values:number|string...):number",
			max,
			max,
			EmptyGuard,
			call,
			converted...,
		)
	},

	"MIN": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return callNumbersFunction(
			"MIN(values:number...):number",
			min,
			min,
			EmptyGuard,
			call,
			values...)
	},

	"MINA": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		converted, failed := parseStringExpressions(call, values)
		if failed != nil {
			return nil, ErrUnsupportedArgument("MINA(values:number|string...):number",
				call, failed)
		}
		return callNumbersFunction(
			"MINA(values:number|string...):number",
			min,
			min,
			EmptyGuard,
			call,
			converted...)
	},

	"ABS": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ABS(value:number):number"
		return callNumbersFunction(format, abs, abs, MakeArityGuard(format, 1), call, values...)
	},

	"CEILING": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "CEILING(value:number, significance:[number]):number"
		return RoundUp(format, call, values...)
	},

	"FLOOR": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "FLOOR(value:number, significance:[number]):number"
		return RoundDown(format, call, values...)
	},

	"ROUND": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ROUND(value:number, places:[number]):number"
		return Round(format, call, values...)
	},

	"POWER": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "POWER(base:number, exponent:number):number"
		return Power(format, call, values...)
	},

	"INT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return Int(call, values...)
	},

	"MOD": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "MOD(dividend:number, divisor:number):number"
		guard := MakeExactTypesGuard(format, ast.IsNumeric, ast.IsNumeric)
		return callNumbersFunction(format, mod, mod, guard, call, values...)
	},

	"SQRT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "SQRT(value:number):number"
		return Sqrt(format, call, values...)
	},

	"CONCATENATE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "CONCATENATE(values:string...):string"
		return Concat(format, call, values...)
	},

	"LEN": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "LEN(value:string):number"
		return Len(format, call, values...)
	},

	"LOWER": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "LOWER(value:string):string"
		return Lower(format, call, values...)
	},

	"UPPER": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "UPPER(value:string):string"
		return Upper(format, call, values...)
	},

	"TRIM": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "TRIM(value:string):string"
		return Trim(format, call, values...)
	},

	"EXACT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "EXACT(a:string, b:string):boolean"
		return Exact(format, call, values...)
	},

	"FIND": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "FIND(where:string, what:string, [start:int]):number"
		return Find(format, call, values...)
	},

	"LEFT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "LEFT(value:string, [amount:int]):string"
		return Left(format, call, values...)
	},

	"RIGHT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "RIGHT(value:string, [amount:int]):string"
		return Right(format, call, values...)
	},

	"MID": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "MID(value:string, start:int, amount:int):string"
		return Mid(format, call, values...)
	},

	"SUBSTITUTE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "SUBSTITUTE(text:string, old:string, new:string, [instances:int]):string"
		return Substitute(format, call, values...)
	},

	"VALUE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "VALUE(value:string):number"
		return Value(format, call, values...)
	},

	"IF": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "IF(predicate:boolean, positive:any, negative:any):any"
		return If(format, call, values...)
	},

	"NOT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "NOT(value:boolean):boolean"
		return Not(format, call, values...)
	},

	"AND": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "AND(a:boolean, b:boolean):boolean"
		return And(format, call, values...)
	},

	"OR": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "OR(a:boolean, b:boolean):boolean"
		return Or(format, call, values...)
	},

	"TRUE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "TRUE():boolean"
		return True(format, call, values...)
	},

	"FALSE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "FALSE():boolean"
		return False(format, call, values...)
	},

	"TODATE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "TODATE(layout:string, value:string):date"
		return ToDate(format, call, values...)
	},

	"FROMDATE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "FROMDATE(layout:string, source:date):string"
		return FromDate(format, call, values...)
	},

	"DAY": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "DAY(value:date):number"
		return Day(format, call, values...)
	},

	"HOUR": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "HOUR(value:date):number"
		return Hour(format, call, values...)
	},

	"MINUTE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "MINUTE(value:date):number"
		return Minute(format, call, values...)
	},

	"MONTH": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "MONTH(value:date):number"
		return Month(format, call, values...)
	},

	"SECOND": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "SECOND(value:date):number"
		return Second(format, call, values...)
	},

	"YEAR": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "YEAR(value:date):number"
		return Year(format, call, values...)
	},

	"WEEKDAY": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "WEEKDAY(value:date):number"
		return Weekday(format, call, values...)
	},

	"NOW": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "NOW():date"
		return Now(format, call, values...)
	},

	"DATE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "DATE(year:number, month:number, day:number):date"
		return Date(format, call, values...)
	},

	"DATEDIF": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "DATEDIF(start:date, end:date, unit:string):number"
		return DateDiff(format, call, values...)
	},

	"DAYS": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "DAYS(start:date, end:date):number"
		return Days(format, call, values...)
	},

	"DATEVALUE": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "DATEVALUE(value:string):date"
		return DateValue(format, call, values...)
	},

	"COUNT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return count(call, values...), nil
	},

	"COUNTA": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		return counta(call, values...), nil
	},

	"ISNUMBER": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ISNUMBER(value:any):boolean"
		return IsNumber(format, call, values...)
	},

	"ISTEXT": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ISTEXT(value:any):boolean"
		return IsText(format, call, values...)
	},

	"ISLOGICAL": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ISLOGICAL(value:any):boolean"
		return IsBoolean(format, call, values...)
	},

	"ISBLANK": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ISBLANK(value:any):boolean"
		return IsBlank(format, call, values...)
	},

	"ADDRESS": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ADDRESS(row:int, column:int):string"
		return Address(format, call, values...)
	},

	"ROW": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "ROW(cell:string):int"
		return Row(format, call, values...)
	},

	"COLUMN": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "COLUMN(cell:string):int"
		return Column(format, call, values...)
	},

	"REF": func(context map[string]string, input [][]string, formats map[string]string,
		call ast.CallExpression, values ...ast.Node,
	) (ast.Node, error) {
		format := "REF(address:string):any"
		return Ref(context, input, formats, format, call, values...)
	},
}

Functions

func Address

func Address(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func And

func And(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Column

func Column(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Concat

func Concat(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Date

func Date(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func DateDiff

func DateDiff(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func DateValue

func DateValue(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Day

func Day(format string, call ast.CallExpression, values ...ast.Node) (ast.Node, error)

func Days

func Days(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func EmptyGuard

func EmptyGuard(function ast.CallExpression, values ...ast.Node) error

func ErrExecute added in v0.1.16

func ErrExecute(err error) error

func ErrExecuting

func ErrExecuting(format string, function ast.CallExpression, err error) error

func ErrExpand added in v0.1.16

func ErrExpand(err error) error

func ErrParse added in v0.2.4

func ErrParse(typeName string, value string, err error) error

func ErrParseBoolean added in v0.1.16

func ErrParseBoolean(err error) error

func ErrParseDate added in v0.1.16

func ErrParseDate(value, format string) error

func ErrParseFloat added in v0.1.16

func ErrParseFloat(err error) error

func ErrParseInt added in v0.1.16

func ErrParseInt(err error) error

func ErrParseWithFormat

func ErrParseWithFormat(input, format, reason string) error

func ErrUnsupportedArgument

func ErrUnsupportedArgument(
	format string,
	function ast.CallExpression,
	argument ast.Node,
) error

func ErrUnsupportedArity

func ErrUnsupportedArity(format string, function ast.CallExpression, expected, given int) error

func ErrUnsupportedExpressionType

func ErrUnsupportedExpressionType(expr ast.Node) error

func ErrUnsupportedFunction

func ErrUnsupportedFunction(function ast.CallExpression) error

func Exact

func Exact(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Exec

func Exec(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func False

func False(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Find

func Find(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func FromDate

func FromDate(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Hour

func Hour(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func If

func If(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Int

func Int(call ast.CallExpression, values ...ast.Node) (ast.Node, error)

func IsBlank

func IsBlank(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func IsBoolean

func IsBoolean(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func IsNumber

func IsNumber(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func IsText

func IsText(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Left

func Left(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Len

func Len(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Lower

func Lower(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Mid

func Mid(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Minute

func Minute(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Month

func Month(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Not

func Not(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Now

func Now(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func NumericGuard

func NumericGuard(function ast.CallExpression, values ...ast.Node) error

func Or

func Or(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func ParseDateWithoutFormat

func ParseDateWithoutFormat(value string) (*time.Time, error)

func ParseWithoutFormat

func ParseWithoutFormat(value string) (ast.Node, error)

ParseWithoutFormat parses a value without format specification using default rules

func Power

func Power(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func ReadValue

func ReadValue(value string, format string) (ast.Node, error)

func Ref

func Ref(
	context map[string]string, input [][]string, formats map[string]string,
	format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)
func Right(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Round

func Round(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func RoundDown

func RoundDown(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func RoundUp

func RoundUp(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Row

func Row(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func RunFunctionTest

func RunFunctionTest(t *testing.T, functionName string, testcases []InfoTestCase,
	context map[string]string, input [][]string, formats map[string]string,
)

RunFunctionTest executes test cases for info functions (ISNUMBER, ISTEXT, ISLOGICAL, ISBLANK)

func Second

func Second(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Sqrt

func Sqrt(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Substitute

func Substitute(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func ToDate

func ToDate(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func Trim

func Trim(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func True

func True(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Upper

func Upper(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Value

func Value(format string,
	call ast.CallExpression, values ...ast.Node,
) (ast.Node, error)

func Weekday

func Weekday(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

func WriteValue

func WriteValue(value ast.Node, format string) (string, error)

WriteValue writes an AST expression to context with optional format specification

func Year

func Year(
	format string,
	call ast.CallExpression,
	values ...ast.Node,
) (ast.Node, error)

Types

type CallGuard

type CallGuard func(ast.CallExpression, ...ast.Node) error

func MakeArityGuard

func MakeArityGuard(format string, arity int) CallGuard

func MakeExactTypesGuard

func MakeExactTypesGuard(format string, guards ...typeGuard) CallGuard

func MakeSameTypeGuard

func MakeSameTypeGuard(format string, guard typeGuard) CallGuard

type InfoTestCase

type InfoTestCase struct {
	Name     string
	Input    []ast.Node
	Expected string
	Error    string
}

InfoTestCase defines the structure for info function test cases

type InternalFunc

type InternalFunc = func(context map[string]string, input [][]string, formats map[string]string,
	call ast.CallExpression, args ...ast.Node) (ast.Node, error)

type MathFunction

type MathFunction[T Number] func(values ...T) T

type Number

type Number interface {
	constraints.Integer | constraints.Float
}

Jump to

Keyboard shortcuts

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