helpers

package
v1.13.21 Latest Latest
Warning

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

Go to latest
Published: Apr 13, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package helpers provides shared utility functions for primitive implementations.

This package centralizes reusable patterns for implementing Scheme primitives:

Numeric Operations

Comparisons

Type Conversion

Sequence Accessors

  • SequenceLength: generic length for Vector/ByteVector
  • SequenceRef: generic indexed read with element conversion closure
  • SequenceSet: generic indexed mutation with element setter closure

List Operations

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssocLookup

func AssocLookup(
	mc machine.CallContext,
	name string,
	eq func(a, b values.Value) bool,
) error

AssocLookup is a helper for alist lookup primitives (assq, assv, assoc). Takes key at index 0, alist at index 1. Uses eq predicate to find match.

func CharCompare

func CharCompare(mc machine.CallContext, name string, cmp func(a, b rune) bool) error

CharCompare is a helper for binary character comparison primitives. It extracts two characters from the primitive's arguments and applies the comparator.

func CharCompareVariadic

func CharCompareVariadic(mc machine.CallContext, name string, cmp func(a, b rune) bool) error

CharCompareVariadic is a helper for variadic character comparison primitives. It extracts characters from the variadic args and applies the comparator pairwise.

func CheckIndexBounds added in v1.2.0

func CheckIndexBounds(idx int64, length int, name string) error

CheckIndexBounds validates that idx is in range [0, length). Returns a wrapped ErrIndexOutOfRange error if the index is out of bounds.

func CollectStrings added in v1.5.0

func CollectStrings(rest values.Value, name string) ([]*values.String, [][]rune, int, error)

CollectStrings extracts zero or more strings from a rest argument, validates that each element is a string, converts them to rune slices, and returns the minimum length of the strings. Callers are responsible for rejecting an empty argument list if a non-empty list is required. Used by string-map and string-for-each.

func CollectVectors added in v1.2.0

func CollectVectors(rest values.Value, name string) ([]*values.Vector, int, error)

CollectVectors extracts a non-empty list of vectors from a rest argument, validates that each element is a vector, and returns the minimum length. Used by vector-map, vector-for-each, and vector-append.

func ComplexOrFloat

func ComplexOrFloat(c complex128) values.Value

ComplexOrFloat returns a Float if the imaginary part is zero, otherwise returns a Complex. This follows R7RS behavior where real results are returned as real numbers. Special case: If both parts are NaN, returns Float(NaN) since this typically results from operations on real NaN inputs.

func EqIdentity added in v1.6.0

func EqIdentity(a, b values.Value) bool

EqIdentity implements eq? semantics: pointer identity for all types except symbols, which compare by name (R7RS §6.1, §6.5).

func Eqv

func Eqv(a, b values.Value) bool

Eqv is a helper implementing eqv? semantics for memv and assv.

R7RS §6.1: eqv? returns #t for numbers that are = and both exact or both inexact. For exact integers (Integer and BigInteger), this means comparing numeric values.

func ExtractInteger added in v1.3.0

func ExtractInteger(v values.Value, name string) (int64, *big.Int, bool, error)

ExtractInteger extracts an integer value from Integer, BigInteger, or Float (if integral). Returns (int64Value, bigIntValue, isInexact, error). If bigIntValue is non-nil, use that; otherwise use int64Value.

R7RS §6.2.6: Integer operations accept exact and inexact integer arguments.

func ExtractReal added in v1.3.0

func ExtractReal(v values.Value, name string) (float64, bool, error)

ExtractReal extracts a float64 from a real number, tracking exactness. Returns the float64 value, whether the input was exact, and any error.

R7RS §6.2.6: Division procedures work on all real numbers.

func FloorDivide

func FloorDivide(n0, n1 int64) (q, r int64)

FloorDivide performs floor division, returning quotient and remainder.

func ForEachList added in v1.10.7

func ForEachList(ctx context.Context, t values.Tuple, name string, fn func(context.Context, int, bool, values.Value) error) error

ForEachList calls fn on each element of t and returns ErrNotAList if the tail is not an empty list (i.e., t is an improper list). If fn returns an error, that error is returned unchanged.

func GcdInt

func GcdInt(a, b int64) int64

GcdInt returns the greatest common divisor of two integers.

func IntegerFold

func IntegerFold(
	mc machine.CallContext,
	op FoldOp,
	identity int64,
	combiner func(acc, val int64) (int64, bool),
) error

IntegerFold is a helper for integer fold operations (gcd, lcm). Takes rest args at index 0, applies absolute value, then folds with combiner.

R7RS §6.2.6: gcd and lcm accept either exact or inexact integer arguments and always return an integer. If any argument is inexact, the result is inexact.

The fold pattern combines a list into a single value using a binary operation:

fold(f, identity, [a, b, c]) = f(f(f(identity, a), b), c)

See SRFI-1 (List Library) for the canonical Scheme definition of fold:

https://srfi.schemers.org/srfi-1/srfi-1.html

func ListToVector

func ListToVector(mc machine.CallContext, name string) error

ListToVector is a helper that converts a list argument to a vector.

func MakeCharPredicate added in v1.5.0

func MakeCharPredicate(name string, test func(rune) bool) machine.ForeignFunction

MakeCharPredicate creates a character predicate primitive that extracts arg 0 as a Character and applies a boolean test on the rune value.

func MakeCharTransform added in v1.5.0

func MakeCharTransform(name string, transform func(rune) rune) machine.ForeignFunction

MakeCharTransform creates a character transformation primitive that extracts arg 0 as a Character, applies a rune transformation, and returns a new Character.

func MakeNumericPredicate added in v1.2.0

func MakeNumericPredicate[T any](
	name string,
	sentinel error,
	test func(T) bool,
) machine.ForeignFunction

MakeNumericPredicate creates a numeric predicate primitive that extracts arg 0 via RequireArg[T] and applies a boolean test. Unlike MakeTypePredicate, this returns an error if the argument doesn't satisfy the type constraint (e.g., "exact? requires a number").

T is typically values.Number or values.RealNumber.

func MakeTypePredicate

func MakeTypePredicate(check func(values.Value) bool) machine.ForeignFunction

MakeTypePredicate creates a type predicate primitive function. The check function should return true if the value matches the expected type.

func MaybeToInexact

func MaybeToInexact(n values.Number, hasInexact bool) values.Value

MaybeToInexact converts an exact number to inexact if needed. If the number is already inexact or hasInexact is false, returns it unchanged.

func MemberLookup added in v1.5.0

func MemberLookup(
	mc machine.CallContext,
	name string,
	eq func(a, b values.Value) bool,
) error

MemberLookup is a helper for list membership primitives (memq, memv). Takes obj at index 0, list at index 1. Uses eq predicate to find match. On match, returns the tail of the list starting at the matched element.

func NumericChainCompare

func NumericChainCompare(
	mc machine.CallContext,
	name string,
	fails func(prev, curr values.Number) bool,
) error

NumericChainCompare is a helper for numeric chain comparison primitives. First arg at index 0, rest at index 1. Returns true if all consecutive pairs satisfy the comparator, false otherwise.

func NumericChainCompareReal added in v1.3.0

func NumericChainCompareReal(
	mc machine.CallContext,
	name string,
	fails func(prev, curr values.Number) bool,
) error

NumericChainCompareReal is a helper for ordering comparison primitives (<, >, <=, >=). It wraps NumericChainCompare with complex-number rejection: any non-real complex argument causes an immediate error rather than a boolean #f result.

The fails callback should return true when the comparison fails (i.e. the pair does not satisfy the ordering relation), false when it succeeds.

func NumericExtremum

func NumericExtremum(
	mc machine.CallContext,
	name string,
	isBetter func(candidate, current values.Number) bool,
) error

NumericExtremum is a helper for min/max primitives. First arg at index 0, rest at index 1. Returns the extremum value where isBetter returns true if candidate should replace current. Per R7RS, if any argument is inexact, the result is inexact.

func NumericFoldVariadic

func NumericFoldVariadic(
	mc machine.CallContext,
	name string,
	identity values.Number,
	binOp func(acc, val values.Number) (values.Number, error),
) error

NumericFoldVariadic is a helper for variadic arithmetic operations (+ and *). It takes a rest parameter at index 0 and folds with the binary operation. Returns identity for empty list, first arg for single element.

func NumericFoldWithFirst

func NumericFoldWithFirst(
	mc machine.CallContext,
	name string,
	unaryOp func(val values.Number) (values.Number, error),
	binOp func(acc, val values.Number) (values.Number, error),
) error

NumericFoldWithFirst is a helper for arithmetic operations with required first arg (- and /). First arg at index 0, rest at index 1. Applies unaryOp for single arg case.

func OptionalArg added in v1.5.0

func OptionalArg[T any](rest values.Value, defaultVal T, sentinel error, name string) (T, error)

OptionalArg extracts an optional typed argument from variadic rest args. If no argument is present, defaultVal is returned. If present but not of type T, an error using sentinel and name is returned.

func ParseOptionalArg added in v1.3.0

func ParseOptionalArg(rest values.Value) (values.Value, bool)

ParseOptionalArg extracts a single optional argument from variadic rest args. Returns the value and true if present, or nil and false if rest is empty or not a valid argument list.

func ParseOptionalStartEnd added in v1.1.0

func ParseOptionalStartEnd(rest values.Value, defaultEnd int64, name string) (int64, int64, error)

ParseOptionalStartEnd extracts optional [start [end]] integer arguments from a rest list. defaultEnd is the value used if end is not provided. name is used in error messages (e.g., "bytevector-copy").

func ParseSubrange added in v1.2.0

func ParseSubrange(rest values.Value, length int, name string) (int, int, error)

ParseSubrange extracts optional [start [end]] from a rest list, validates bounds against length, and returns the range as int values. This bundles ParseOptionalStartEnd + ValidateStartEnd + int conversion for the common case where the caller works with int-indexed collections.

func RequireArg added in v1.1.0

func RequireArg[T any](mc machine.CallContext, index int, sentinel error, name string) (T, error)

RequireArg extracts mc.Arg(index) and asserts it has concrete type T. On failure it returns a wrapped error using the given sentinel and primitive name. The error message format is "<name>: expected <type> but got <actual>", where <type> is derived from the sentinel message by trimming the "not " prefix (e.g., ErrNotAVector "not a vector" → "a vector").

func RequireIndex added in v1.2.0

func RequireIndex(mc machine.CallContext, argIdx int, length int, name string) (int, error)

RequireIndex extracts an exact integer index from mc.Arg(argIdx) and validates it is in range [0, length). Accepts *Integer, *BigInteger, and integer-valued *Rational via values.ExactInteger, which is more R7RS-correct than requiring *Integer alone (R7RS §6.1: indices are exact non-negative integers).

func RequireType added in v1.1.0

func RequireType[T any](v values.Value, sentinel error, name string) (T, error)

RequireType asserts that v has concrete type T. On failure it returns a wrapped error using the given sentinel and primitive name.

func SequenceLength added in v1.2.0

func SequenceLength[T interface{ Length() int }](
	mc machine.CallContext,
	sentinel error,
	name string,
) error

SequenceLength extracts a sequence of type T from arg 0, and sets the machine context value to its length as an exact integer. T must be a pointer type satisfying interface{ Length() int }.

func SequenceRef added in v1.2.0

func SequenceRef[T interface{ Length() int }](
	mc machine.CallContext,
	sentinel error,
	name string,
	getElement func(T, int) values.Value,
) error

SequenceRef extracts a sequence of type T from arg 0, validates an exact integer index from arg 1, and sets the machine context value to getElement(seq, idx). The getElement closure handles type-specific element retrieval (e.g., Vector.Get vs ByteVector byte-to-integer conversion).

func SequenceSet added in v1.2.0

func SequenceSet[T interface{ Length() int }](
	mc machine.CallContext,
	sentinel error,
	name string,
	setElement func(T, int, machine.CallContext) error,
) error

SequenceSet extracts a sequence of type T from arg 0, validates an exact integer index from arg 1, and delegates to setElement(seq, idx, mc) for the type-specific mutation. Sets Void on success.

func StringCompare

func StringCompare(mc machine.CallContext, name string, cmp func(a, b string) bool) error

StringCompare is a helper for binary string comparison primitives. It extracts two strings from the primitive's arguments and applies the comparator.

func StringCompareVariadic

func StringCompareVariadic(mc machine.CallContext, name string, cmp func(a, b string) bool) error

StringCompareVariadic is a helper for variadic string comparison primitives. It extracts strings from the variadic args and applies the comparator pairwise.

func ToComplex128

func ToComplex128(v values.Value) (complex128, error)

ToComplex128 converts a Scheme number to a Go complex128. This supports all numeric types: Integer, BigInteger, Float, BigFloat, Rational, Complex, and BigComplex.

func ToFloat64

func ToFloat64(v values.Value) (float64, error)

ToFloat64 converts a Scheme real number to a Go float64, covering the full real numeric tower: Integer, BigInteger, Float, BigFloat, and Rational. Complex types are excluded — they cannot be reduced to a single float64 without information loss. Use ToComplex128 for complex values.

func ValidateStartEnd added in v1.2.0

func ValidateStartEnd(start, end, length int64, name string) error

ValidateStartEnd checks the invariant 0 <= start <= end <= length. Returns a wrapped ErrIndexOutOfRange error if any bound is violated.

Types

type FoldOp

type FoldOp int

FoldOp represents the type of fold operation for integers.

const (
	FoldOpGCD FoldOp = iota
	FoldOpLCM
)

Jump to

Keyboard shortcuts

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