exprcore

package
v0.0.0-...-fb7d6bd Latest Latest
Warning

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

Go to latest
Published: May 25, 2021 License: BSD-3-Clause Imports: 26 Imported by: 2

Documentation

Overview

Package exprcore provides a exprcore interpreter.

exprcore values are represented by the Value interface. The following built-in Value types are known to the evaluator:

NoneType        -- NoneType
Bool            -- bool
Int             -- int
Float           -- float
String          -- string
*List           -- list
Tuple           -- tuple
*Dict           -- dict
*Set            -- set
*Function       -- function (implemented in exprcore)
*Builtin        -- builtin_function_or_method (function or method implemented in Go)

Client applications may define new data types that satisfy at least the Value interface. Such types may provide additional operations by implementing any of these optional interfaces:

Callable        -- value is callable like a function
Comparable      -- value defines its own comparison operations
Iterable        -- value is iterable using 'for' loops
Sequence        -- value is iterable sequence of known length
Indexable       -- value is sequence with efficient random access
Mapping         -- value maps from keys to values, like a dictionary
HasBinary       -- value defines binary operations such as * and +
HasAttrs        -- value has readable fields or methods x.f
HasSetField     -- value has settable fields x.f
HasSetIndex     -- value supports element update using x[i]=y
HasSetKey       -- value supports map update using x[k]=v
HasUnary        -- value defines unary operations such as + and -

Client applications may also define domain-specific functions in Go and make them available to exprcore programs. Use NewBuiltin to construct a built-in value that wraps a Go function. The implementation of the Go function may use UnpackArgs to make sense of the positional and keyword arguments provided by the caller.

exprcore's None value is not equal to Go's nil. Go's nil is not a legal exprcore value, but the compiler will not stop you from converting nil to Value. Be careful to avoid allowing Go nil values to leak into exprcore data structures.

The Compare operation requires two arguments of the same type, but this constraint cannot be expressed in Go's type system. (This is the classic "binary method problem".) So, each Value type's CompareSameType method is a partial function that compares a value only against others of the same type. Use the package's standalone Compare (or Equal) function to compare an arbitrary pair of values.

To parse and evaluate a exprcore source file, use ExecFile. The Eval function evaluates a single expression. All evaluator functions require a Thread parameter which defines the "thread-local storage" of a exprcore thread and may be used to plumb application state through exprcore code and into callbacks. When evaluation fails it returns an EvalError from which the application may obtain a backtrace of active exprcore calls.

Index

Examples

Constants

View Source
const CompilerVersion = compile.Version

CompilerVersion is the version number of the protocol for compiled files. Applications must not run programs compiled by one version with an interpreter at another version, and should thus incorporate the compiler version into the cache key when reusing compiled code.

View Source
const Default = String("prototype")

Default is the default constructor for structs. It is merely the string "struct".

View Source
const None = NoneType(0)

Variables

View Source
var CallContinue = errors.New("continue call")
View Source
var ErrFrozen = errors.New("unable to change frozen prototype")
View Source
var Root = &Prototype{
	constructor: Default,
	frozen:      true,
}
View Source
var StopChain = errors.New("stop chain")

Functions

func AsFloat

func AsFloat(x Value) (f float64, ok bool)

AsFloat returns the float64 value closest to x. The f result is undefined if x is not a float or int.

func AsInt32

func AsInt32(x Value) (int, error)

AsInt32 returns the value of x if is representable as an int32.

func AsString

func AsString(x Value) (string, bool)

func Compare

func Compare(op syntax.Token, x, y Value) (bool, error)

Compare compares two exprcore values. The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE. Compare returns an error if an ordered comparison was requested for a type that does not support it.

Recursive comparisons by implementations of Value.CompareSameType should use CompareDepth to prevent infinite recursion.

func CompareDepth

func CompareDepth(op syntax.Token, x, y Value, depth int) (bool, error)

CompareDepth compares two exprcore values. The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE. CompareDepth returns an error if an ordered comparison was requested for a pair of values that do not support it.

The depth parameter limits the maximum depth of recursion in cyclic data structures.

func Equal

func Equal(x, y Value) (bool, error)

Equal reports whether two exprcore values are equal.

func EqualDepth

func EqualDepth(x, y Value, depth int) (bool, error)

EqualDepth reports whether two exprcore values are equal.

Recursive comparisons by implementations of Value.CompareSameType should use EqualDepth to prevent infinite recursion.

func ExecREPLChunk

func ExecREPLChunk(f *syntax.File, thread *Thread, globals StringDict) error

ExecREPLChunk compiles and executes file f in the specified thread and global environment. This is a variant of ExecFile specialized to the needs of a REPL, in which a sequence of input chunks, each syntactically a File, manipulates the same set of module globals, which are not frozen after execution.

This function is intended to support only github.com/lab47/exprcore/repl. Its API stability is not guaranteed.

func Len

func Len(x Value) int

Len returns the length of a string or sequence value, and -1 for all others.

Warning: Len(x) >= 0 does not imply Iterate(x) != nil. A string has a known length but is not directly iterable.

func StartProfile

func StartProfile(w io.Writer) error

StartProfile enables time profiling of all exprcore threads, and writes a profile in pprof format to w. It must be followed by a call to StopProfiler to stop the profiler and finalize the profile.

StartProfile returns an error if profiling was already enabled.

StartProfile must not be called concurrently with exprcore execution.

func StopProfile

func StopProfile() error

StopProfiler stops the profiler started by a prior call to StartProfile and finalizes the profile. It returns an error if the profile could not be completed.

StopProfiler must not be called concurrently with exprcore execution.

func UnpackArgs

func UnpackArgs(fnname string, args Tuple, kwargs []Tuple, pairs ...interface{}) error

UnpackArgs unpacks the positional and keyword arguments into the supplied parameter variables. pairs is an alternating list of names and pointers to variables.

If the variable is a bool, int, string, *List, *Dict, Callable, Iterable, or user-defined implementation of Value, UnpackArgs performs the appropriate type check. An int uses the AsInt32 check. If the parameter name ends with "?", it and all following parameters are optional.

If the variable implements Unpacker, its Unpack argument is called with the argument value, allowing an application to define its own argument validation and conversion.

If the variable implements Value, UnpackArgs may call its Type() method while constructing the error message.

Beware: an optional *List, *Dict, Callable, Iterable, or Value variable that is not assigned is not a valid exprcore Value, so the caller must explicitly handle such cases by interpreting nil as None or some computed default.

func UnpackPositionalArgs

func UnpackPositionalArgs(fnname string, args Tuple, kwargs []Tuple, min int, vars ...interface{}) error

UnpackPositionalArgs unpacks the positional arguments into corresponding variables. Each element of vars is a pointer; see UnpackArgs for allowed types and conversions.

UnpackPositionalArgs reports an error if the number of arguments is less than min or greater than len(vars), if kwargs is nonempty, or if any conversion fails.

Types

type Bool

type Bool bool

Bool is the type of a exprcore bool.

const (
	False Bool = false
	True  Bool = true
)

func (Bool) CompareSameType

func (x Bool) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (Bool) Freeze

func (b Bool) Freeze()

func (Bool) Hash

func (b Bool) Hash() (uint32, error)

func (Bool) String

func (b Bool) String() string

func (Bool) Truth

func (b Bool) Truth() Bool

func (Bool) Type

func (b Bool) Type() string

type Builtin

type Builtin struct {
	Prototype
	// contains filtered or unexported fields
}

A Builtin is a function implemented in Go.

func NewBuiltin

func NewBuiltin(name string, fn func(thread *Thread, fn *Builtin, args Tuple, kwargs []Tuple) (Value, error)) *Builtin

NewBuiltin returns a new 'builtin_function_or_method' value with the specified name and implementation. It compares unequal with all other values.

func (*Builtin) Attr

func (b *Builtin) Attr(name string) (Value, error)

func (*Builtin) BindReceiver

func (b *Builtin) BindReceiver(recv Value) *Builtin

BindReceiver returns a new Builtin value representing a method closure, that is, a built-in function bound to a receiver value.

In the example below, the value of f is the string.index built-in method bound to the receiver value "abc":

f = "abc".index; f("a"); f("b")

In the common case, the receiver is bound only during the call, but this still results in the creation of a temporary method closure:

"abc".index("a")

func (*Builtin) CallInternal

func (b *Builtin) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)

func (*Builtin) Freeze

func (b *Builtin) Freeze()

func (*Builtin) Hash

func (b *Builtin) Hash() (uint32, error)

func (*Builtin) Name

func (b *Builtin) Name() string

func (*Builtin) Receiver

func (b *Builtin) Receiver() Value

func (*Builtin) String

func (b *Builtin) String() string

func (*Builtin) Truth

func (b *Builtin) Truth() Bool

func (*Builtin) Type

func (b *Builtin) Type() string

type CallFrame

type CallFrame struct {
	Name string
	Pos  syntax.Position
}

A CallFrame represents the function name and current position of execution of an enclosing call frame.

type CallStack

type CallStack []CallFrame

A CallStack is a stack of call frames, outermost first.

func (CallStack) At

func (stack CallStack) At(i int) CallFrame

At returns a copy of the frame at depth i. At(0) returns the topmost frame.

func (*CallStack) Pop

func (stack *CallStack) Pop() CallFrame

Pop removes and returns the topmost frame.

func (CallStack) String

func (stack CallStack) String() string

String returns a user-friendly description of the stack.

type Callable

type Callable interface {
	Value
	Name() string
	CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)
}

A Callable value f may be the operand of a function call, f(x).

Clients should use the Call function, never the CallInternal method.

type Comparable

type Comparable interface {
	Value
	// CompareSameType compares one value to another of the same Type().
	// The comparison operation must be one of EQL, NEQ, LT, LE, GT, or GE.
	// CompareSameType returns an error if an ordered comparison was
	// requested for a type that does not support it.
	//
	// Implementations that recursively compare subcomponents of
	// the value should use the CompareDepth function, not Compare, to
	// avoid infinite recursion on cyclic structures.
	//
	// The depth parameter is used to bound comparisons of cyclic
	// data structures.  Implementations should decrement depth
	// before calling CompareDepth and should return an error if depth
	// < 1.
	//
	// Client code should not call this method.  Instead, use the
	// standalone Compare or Equals functions, which are defined for
	// all pairs of operands.
	CompareSameType(op syntax.Token, y Value, depth int) (bool, error)
}

A Comparable is a value that defines its own equivalence relation and perhaps ordered comparisons.

type DebugFrame

type DebugFrame interface {
	Callable() Callable        // returns the frame's function
	Local(i int) Value         // returns the value of the (exprcore) frame's ith local variable
	Position() syntax.Position // returns the current position of execution in this frame
}

DebugFrame is the debugger API for a frame of the interpreter's call stack.

Most applications have no need for this API; use CallFrame instead.

Clients must not retain a DebugFrame nor call any of its methods once the current built-in call has returned or execution has resumed after a breakpoint as this may have unpredictable effects, including but not limited to retention of object that would otherwise be garbage.

type Dict

type Dict struct {
	Prototype
	// contains filtered or unexported fields
}

A *Dict represents a exprcore dictionary. The zero value of Dict is a valid empty dictionary. If you know the exact final number of entries, it is more efficient to call NewDict.

func NewDict

func NewDict(size int) *Dict

NewDict returns a set with initial space for at least size insertions before rehashing.

func (*Dict) Attr

func (d *Dict) Attr(name string) (Value, error)

func (*Dict) Clear

func (d *Dict) Clear() error

func (*Dict) CompareSameType

func (x *Dict) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (*Dict) Delete

func (d *Dict) Delete(k Value) (v Value, found bool, err error)

func (*Dict) Freeze

func (d *Dict) Freeze()

func (*Dict) Get

func (d *Dict) Get(k Value) (v Value, found bool, err error)

func (*Dict) Hash

func (d *Dict) Hash() (uint32, error)

func (*Dict) Items

func (d *Dict) Items() []Tuple

func (*Dict) Iterate

func (d *Dict) Iterate() Iterator

func (*Dict) Keys

func (d *Dict) Keys() []Value

func (*Dict) Len

func (d *Dict) Len() int

func (*Dict) SetKey

func (d *Dict) SetKey(k, v Value) error

func (*Dict) String

func (d *Dict) String() string

func (*Dict) Truth

func (d *Dict) Truth() Bool

func (*Dict) Type

func (d *Dict) Type() string

func (*Dict) Values

func (d *Dict) Values() []Value

type EvalError

type EvalError struct {
	Msg       string
	CallStack CallStack
	// contains filtered or unexported fields
}

An EvalError is a exprcore evaluation error and a copy of the thread's stack at the moment of the error.

func (*EvalError) Backtrace

func (e *EvalError) Backtrace() string

Backtrace returns a user-friendly error message describing the stack of calls that led to this error.

func (*EvalError) Error

func (e *EvalError) Error() string

func (*EvalError) Unwrap

func (e *EvalError) Unwrap() error

type Float

type Float float64

Float is the type of a exprcore float.

func (Float) CompareSameType

func (x Float) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (Float) Freeze

func (f Float) Freeze()

func (Float) Hash

func (f Float) Hash() (uint32, error)

func (Float) Mod

func (x Float) Mod(y Float) Float

func (Float) String

func (f Float) String() string

func (Float) Truth

func (f Float) Truth() Bool

func (Float) Type

func (f Float) Type() string

func (Float) Unary

func (f Float) Unary(op syntax.Token) (Value, error)

Unary implements the operations +float and -float.

type Function

type Function struct {
	Prototype
	// contains filtered or unexported fields
}

A Function is a function defined by a exprcore def statement or lambda expression. The initialization behavior of a exprcore module is also represented by a Function.

func ExprFunc

func ExprFunc(filename string, src interface{}, env StringDict) (*Function, error)

ExprFunc returns a no-argument function that evaluates the expression whose source is src.

func (*Function) Attr

func (fn *Function) Attr(name string) (Value, error)

func (*Function) CallInternal

func (fn *Function) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)

func (*Function) Doc

func (fn *Function) Doc() string

func (*Function) Freeze

func (fn *Function) Freeze()

func (*Function) Globals

func (fn *Function) Globals() StringDict

Globals returns a new, unfrozen StringDict containing all global variables so far defined in the function's module.

func (*Function) HasKwargs

func (fn *Function) HasKwargs() bool

func (*Function) HasVarargs

func (fn *Function) HasVarargs() bool

func (*Function) Hash

func (fn *Function) Hash() (uint32, error)

func (*Function) HashCode

func (fn *Function) HashCode() ([]byte, error)

func (*Function) Name

func (fn *Function) Name() string

func (*Function) NumKwonlyParams

func (fn *Function) NumKwonlyParams() int

func (*Function) NumParams

func (fn *Function) NumParams() int

func (*Function) Param

func (fn *Function) Param(i int) (string, syntax.Position)

Param returns the name and position of the ith parameter, where 0 <= i < NumParams(). The *args and **kwargs parameters are at the end even if there were optional parameters after *args.

func (*Function) Position

func (fn *Function) Position() syntax.Position

func (*Function) String

func (fn *Function) String() string

func (*Function) Truth

func (fn *Function) Truth() Bool

func (*Function) Type

func (fn *Function) Type() string

type HasAttrs

type HasAttrs interface {
	Value
	Attr(name string) (Value, error) // returns (nil, nil) if attribute not present
	AttrNames() []string             // callers must not modify the result.
}

A HasAttrs value has fields or methods that may be read by a dot expression (y = x.f). Attribute names may be listed using the built-in 'dir' function.

For implementation convenience, a result of (nil, nil) from Attr is interpreted as a "no such field or method" error. Implementations are free to return a more precise error.

type HasBinary

type HasBinary interface {
	Value
	Binary(op syntax.Token, y Value, side Side) (Value, error)
}

A HasBinary value may be used as either operand of these binary operators:

  • - * / // % in not in | & ^ << >>

The Side argument indicates whether the receiver is the left or right operand.

An implementation may decline to handle an operation by returning (nil, nil). For this reason, clients should always call the standalone Binary(op, x, y) function rather than calling the method directly.

type HasBindReceiver

type HasBindReceiver interface {
	BindReceiver(recv Value) *Builtin
}

type HasSetField

type HasSetField interface {
	HasAttrs
	SetField(name string, val Value) error
}

A HasSetField value has fields that may be written by a dot expression (x.f = y).

An implementation of SetField may return a NoSuchAttrError, in which case the runtime may augment the error message to warn of possible misspelling.

type HasSetIndex

type HasSetIndex interface {
	Indexable
	SetIndex(index int, v Value) error
}

A HasSetIndex is an Indexable value whose elements may be assigned (x[i] = y).

The implementation should not add Len to a negative index as the evaluator does this before the call.

type HasSetKey

type HasSetKey interface {
	Mapping
	SetKey(k, v Value) error
}

A HasSetKey supports map update using x[k]=v syntax, like a dictionary.

type HasUnary

type HasUnary interface {
	Value
	Unary(op syntax.Token) (Value, error)
}

A HasUnary value may be used as the operand of these unary operators:

  • - ~

An implementation may decline to handle an operation by returning (nil, nil). For this reason, clients should always call the standalone Unary(op, x) function rather than calling the method directly.

type Indexable

type Indexable interface {
	Value
	Index(i int) Value // requires 0 <= i < Len()
	Len() int
}

An Indexable is a sequence of known length that supports efficient random access. It is not necessarily iterable.

type Int

type Int struct {
	// contains filtered or unexported fields
}

Int is the type of a exprcore int.

func MakeBigInt

func MakeBigInt(x *big.Int) Int

MakeBigInt returns a exprcore int for the specified big.Int. The caller must not subsequently modify x.

func MakeInt

func MakeInt(x int) Int

MakeInt returns a exprcore int for the specified signed integer.

func MakeInt64

func MakeInt64(x int64) Int

MakeInt64 returns a exprcore int for the specified int64.

func MakeUint

func MakeUint(x uint) Int

MakeUint returns a exprcore int for the specified unsigned integer.

func MakeUint64

func MakeUint64(x uint64) Int

MakeUint64 returns a exprcore int for the specified uint64.

func NumberToInt

func NumberToInt(x Value) (Int, error)

NumberToInt converts a number x to an integer value. An int is returned unchanged, a float is truncated towards zero. NumberToInt reports an error for all other values.

func (Int) Add

func (x Int) Add(y Int) Int

func (Int) And

func (x Int) And(y Int) Int

func (Int) BigInt

func (i Int) BigInt() *big.Int

BigInt returns the value as a big.Int. The returned variable must not be modified by the client.

func (Int) CompareSameType

func (x Int) CompareSameType(op syntax.Token, v Value, depth int) (bool, error)

func (Int) Div

func (x Int) Div(y Int) Int

Precondition: y is nonzero.

func (Int) Float

func (i Int) Float() Float

Float returns the float value nearest i.

func (Int) Format

func (i Int) Format(s fmt.State, ch rune)

func (Int) Freeze

func (i Int) Freeze()

func (Int) Hash

func (i Int) Hash() (uint32, error)

func (Int) Int64

func (i Int) Int64() (_ int64, ok bool)

Int64 returns the value as an int64. If it is not exactly representable the result is undefined and ok is false.

func (Int) Lsh

func (x Int) Lsh(y uint) Int

func (Int) Mod

func (x Int) Mod(y Int) Int

Precondition: y is nonzero.

func (Int) Mul

func (x Int) Mul(y Int) Int

func (Int) Not

func (x Int) Not() Int

func (Int) Or

func (x Int) Or(y Int) Int

func (Int) Rsh

func (x Int) Rsh(y uint) Int

func (Int) Sign

func (x Int) Sign() int

func (Int) String

func (i Int) String() string

func (Int) Sub

func (x Int) Sub(y Int) Int

func (Int) Truth

func (i Int) Truth() Bool

func (Int) Type

func (i Int) Type() string

func (Int) Uint64

func (i Int) Uint64() (_ uint64, ok bool)

Uint64 returns the value as a uint64. If it is not exactly representable the result is undefined and ok is false.

func (Int) Unary

func (i Int) Unary(op syntax.Token) (Value, error)

Unary implements the operations +int, -int, and ~int.

func (Int) Xor

func (x Int) Xor(y Int) Int

type Iterable

type Iterable interface {
	Value
	Iterate() Iterator // must be followed by call to Iterator.Done
}

An Iterable abstracts a sequence of values. An iterable value may be iterated over by a 'for' loop or used where any other exprcore iterable is allowed. Unlike a Sequence, the length of an Iterable is not necessarily known in advance of iteration.

type IterableMapping

type IterableMapping interface {
	Mapping
	Iterate() Iterator // see Iterable interface
	Items() []Tuple    // a new slice containing all key/value pairs
}

An IterableMapping is a mapping that supports key enumeration.

type Iterator

type Iterator interface {
	// If the iterator is exhausted, Next returns false.
	// Otherwise it sets *p to the current element of the sequence,
	// advances the iterator, and returns true.
	Next(p *Value) bool
	Done()
}

An Iterator provides a sequence of values to the caller.

The caller must call Done when the iterator is no longer needed. Operations that modify a sequence will fail if it has active iterators.

Example usage:

iter := iterable.Iterator()
defer iter.Done()
var x Value
for iter.Next(&x) {
	...
}

func Iterate

func Iterate(x Value) Iterator

Iterate return a new iterator for the value if iterable, nil otherwise. If the result is non-nil, the caller must call Done when finished with it.

Warning: Iterate(x) != nil does not imply Len(x) >= 0. Some iterables may have unknown length.

type List

type List struct {
	Prototype
	// contains filtered or unexported fields
}

A *List represents a exprcore list value.

func NewList

func NewList(elems []Value) *List

NewList returns a list containing the specified elements. Callers should not subsequently modify elems.

func (*List) Append

func (l *List) Append(v Value) error

func (*List) Attr

func (l *List) Attr(name string) (Value, error)

func (*List) Clear

func (l *List) Clear() error

func (*List) CompareSameType

func (x *List) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (*List) Freeze

func (l *List) Freeze()

func (*List) Hash

func (l *List) Hash() (uint32, error)

func (*List) Index

func (l *List) Index(i int) Value

func (*List) Iterate

func (l *List) Iterate() Iterator

func (*List) Len

func (l *List) Len() int

func (*List) SetIndex

func (l *List) SetIndex(i int, v Value) error

func (*List) Slice

func (l *List) Slice(start, end, step int) Value

func (*List) String

func (l *List) String() string

func (*List) Truth

func (l *List) Truth() Bool

func (*List) Type

func (l *List) Type() string

type Mapping

type Mapping interface {
	Value
	// Get returns the value corresponding to the specified key,
	// or !found if the mapping does not contain the key.
	//
	// Get also defines the behavior of "v in mapping".
	// The 'in' operator reports the 'found' component, ignoring errors.
	Get(Value) (v Value, found bool, err error)
}

A Mapping is a mapping from keys to values, such as a dictionary.

If a type satisfies both Mapping and Iterable, the iterator yields the keys of the mapping.

type NoSuchAttrError

type NoSuchAttrError string

A NoSuchAttrError may be returned by an implementation of HasAttrs.Attr or HasSetField.SetField to indicate that no such field exists. In that case the runtime may augment the error message to warn of possible misspelling.

func (NoSuchAttrError) Error

func (e NoSuchAttrError) Error() string

type NoneType

type NoneType byte

NoneType is the type of None. Its only legal value is None. (We represent it as a number, not struct{}, so that None may be constant.)

func (NoneType) CompareSameType

func (NoneType) CompareSameType(op syntax.Token, y Value, depth int) (bool, error)

func (NoneType) Freeze

func (NoneType) Freeze()

func (NoneType) Hash

func (NoneType) Hash() (uint32, error)

func (NoneType) String

func (NoneType) String() string

func (NoneType) Truth

func (NoneType) Truth() Bool

func (NoneType) Type

func (NoneType) Type() string

type Program

type Program struct {
	// contains filtered or unexported fields
}

A Program is a compiled exprcore program.

Programs are immutable, and contain no Values. A Program may be created by parsing a source file (see SourceProgram) or by loading a previously saved compiled program (see CompiledProgram).

func CompiledProgram

func CompiledProgram(in io.Reader) (*Program, error)

CompiledProgram produces a new program from the representation of a compiled program previously saved by Program.Write.

func FileProgram

func FileProgram(f *syntax.File, isPredeclared func(string) bool) (*Program, error)

FileProgram produces a new program by resolving, and compiling the exprcore source file syntax tree. On success, it returns the compiled program.

Resolving a syntax tree mutates it. Do not call FileProgram more than once on the same file.

The isPredeclared predicate reports whether a name is a pre-declared identifier of the current module. Its typical value is predeclared.Has, where predeclared is a StringDict of pre-declared values.

func SourceProgram

func SourceProgram(filename string, src interface{}, isPredeclared func(string) bool) (*syntax.File, *Program, error)

SourceProgram produces a new program by parsing, resolving, and compiling a exprcore source file. On success, it returns the parsed file and the compiled program. The filename and src parameters are as for syntax.Parse.

The isPredeclared predicate reports whether a name is a pre-declared identifier of the current module. Its typical value is predeclared.Has, where predeclared is a StringDict of pre-declared values.

func (*Program) Filename

func (prog *Program) Filename() string

Filename returns the name of the file from which this program was loaded.

func (*Program) Init

func (prog *Program) Init(thread *Thread, predeclared StringDict) (StringDict, Value, error)

Init creates a set of global variables for the program, executes the toplevel code of the specified program, and returns a new, unfrozen dictionary of the globals.

func (*Program) Load

func (prog *Program) Load(i int) (string, syntax.Position)

Load(i) returns the name and position of the i'th module directly loaded by this one, where 0 <= i < NumLoads(). The name is unresolved---exactly as it appears in the source.

func (*Program) NumLoads

func (prog *Program) NumLoads() int

NumLoads returns the number of load statements in the compiled program.

func (*Program) String

func (prog *Program) String() string

func (*Program) Write

func (prog *Program) Write(out io.Writer) error

WriteTo writes the compiled module to the specified output stream.

type Prototype

type Prototype struct {
	// contains filtered or unexported fields
}

Prototype is an immutable exprcore type that maps field names to values. It is not iterable and does not support len.

A struct has a constructor, a distinct value that identifies a class of structs, and which appears in the struct's string representation.

Operations such as x+y fail if the constructors of the two operands are not equal.

The default constructor, Default, is the string "struct", but clients may wish to 'brand' structs for their own purposes. The constructor value appears in the printed form of the value, and is accessible using the Constructor method.

Use Attr to access its fields and AttrNames to enumerate them.

func FromBuiltins

func FromBuiltins(p *Prototype, m map[string]*Builtin) *Prototype

func FromKeywords

func FromKeywords(p *Prototype, kwargs []Tuple) *Prototype

FromKeywords returns a new struct instance whose fields are specified by the key/value pairs in kwargs. (Each kwargs[i][0] must be a String.)

func FromStringDict

func FromStringDict(p *Prototype, d StringDict) *Prototype

FromStringDict returns a whose elements are those of d. The constructor parameter specifies the constructor; use Default for an ordinary struct.

func (*Prototype) AlongChain

func (s *Prototype) AlongChain(f func(p *Prototype) error) error

func (*Prototype) Attr

func (s *Prototype) Attr(name string) (Value, error)

func (*Prototype) AttrNames

func (s *Prototype) AttrNames() []string

AttrNames returns a new sorted list of the struct fields.

func (*Prototype) AttrOf

func (s *Prototype) AttrOf(name string, target Value) (Value, error)

Attr returns the value of the specified field.

func (*Prototype) Binary

func (x *Prototype) Binary(op syntax.Token, y Value, side Side) (Value, error)

func (*Prototype) CallInternal

func (s *Prototype) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Value, error)

func (*Prototype) CompareSameType

func (x *Prototype) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (*Prototype) Constructor

func (s *Prototype) Constructor() Value

Constructor returns the constructor used to create this struct.

func (*Prototype) Freeze

func (s *Prototype) Freeze()

func (*Prototype) Hash

func (s *Prototype) Hash() (uint32, error)

func (*Prototype) Name

func (s *Prototype) Name() string

func (*Prototype) SetField

func (s *Prototype) SetField(name string, v Value) error

SetField sets the entry to name to the given value. If the prototype is frozen returns an error.

func (*Prototype) String

func (s *Prototype) String() string

func (*Prototype) StringAttr

func (s *Prototype) StringAttr(name string) (String, bool, error)

Helper methods to convert types

func (*Prototype) ToList

func (x *Prototype) ToList() (*List, error)

func (*Prototype) ToStringDict

func (s *Prototype) ToStringDict(d StringDict)

ToStringDict adds a name/value entry to d for each field of the struct.

func (*Prototype) Truth

func (s *Prototype) Truth() Bool

func (*Prototype) Type

func (s *Prototype) Type() string

type Sequence

type Sequence interface {
	Iterable
	Len() int
}

A Sequence is a sequence of values of known length.

type Set

type Set struct {
	Prototype
	// contains filtered or unexported fields
}

A Set represents a exprcore set value. The zero value of Set is a valid empty set. If you know the exact final number of elements, it is more efficient to call NewSet.

func NewSet

func NewSet(size int) *Set

NewSet returns a dictionary with initial space for at least size insertions before rehashing.

func (*Set) Attr

func (s *Set) Attr(name string) (Value, error)

func (*Set) Clear

func (s *Set) Clear() error

func (*Set) CompareSameType

func (x *Set) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (*Set) Delete

func (s *Set) Delete(k Value) (found bool, err error)

func (*Set) Freeze

func (s *Set) Freeze()

func (*Set) Has

func (s *Set) Has(k Value) (found bool, err error)

func (*Set) Hash

func (s *Set) Hash() (uint32, error)

func (*Set) Insert

func (s *Set) Insert(k Value) error

func (*Set) Iterate

func (s *Set) Iterate() Iterator

func (*Set) Len

func (s *Set) Len() int

func (*Set) String

func (s *Set) String() string

func (*Set) Truth

func (s *Set) Truth() Bool

func (*Set) Type

func (s *Set) Type() string

func (*Set) Union

func (s *Set) Union(iter Iterator) (Value, error)

type Side

type Side bool
const (
	Left  Side = false
	Right Side = true
)

type Sliceable

type Sliceable interface {
	Indexable
	// For positive strides (step > 0), 0 <= start <= end <= n.
	// For negative strides (step < 0), -1 <= end <= start < n.
	// The caller must ensure that the start and end indices are valid
	// and that step is non-zero.
	Slice(start, end, step int) Value
}

A Sliceable is a sequence that can be cut into pieces with the slice operator (x[i:j:step]).

All native indexable objects are sliceable. This is a separate interface for backwards-compatibility.

type String

type String string

String is the type of a exprcore string.

A String encapsulates an an immutable sequence of bytes, but strings are not directly iterable. Instead, iterate over the result of calling one of these four methods: codepoints, codepoint_ords, elems, elem_ords.

Warning: the contract of the Value interface's String method is that it returns the value printed in exprcore notation, so s.String() or fmt.Sprintf("%s", s) returns a quoted string. Use string(s) or s.GoString() or fmt.Sprintf("%#v", s) to obtain the raw contents of a exprcore string as a Go string.

func (String) Attr

func (s String) Attr(name string) (Value, error)

func (String) AttrNames

func (s String) AttrNames() []string

func (String) CompareSameType

func (x String) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (String) Freeze

func (s String) Freeze()

func (String) GoString

func (s String) GoString() string

func (String) Hash

func (s String) Hash() (uint32, error)

func (String) Index

func (s String) Index(i int) Value

func (String) Len

func (s String) Len() int

func (String) Slice

func (s String) Slice(start, end, step int) Value

func (String) String

func (s String) String() string

func (String) Truth

func (s String) Truth() Bool

func (String) Type

func (s String) Type() string

type StringDict

type StringDict map[string]Value

A StringDict is a mapping from names to values, and represents an environment such as the global variables of a module. It is not a true exprcore.Value.

var Universe StringDict

Universe defines the set of universal built-ins, such as None, True, and len.

The Go application may add or remove items from the universe dictionary before exprcore evaluation begins. All values in the dictionary must be immutable. exprcore programs cannot modify the dictionary.

func ExecFile

func ExecFile(thread *Thread, filename string, src interface{}, predeclared StringDict) (StringDict, error)

ExecFile parses, resolves, and executes a exprcore file in the specified global environment, which may be modified during execution.

Thread is the state associated with the exprcore thread.

The filename and src parameters are as for syntax.Parse: filename is the name of the file to execute, and the name that appears in error messages; src is an optional source of bytes to use instead of filename.

predeclared defines the predeclared names specific to this module. Execution does not modify this dictionary, though it may mutate its values.

If ExecFile fails during evaluation, it returns an *EvalError containing a backtrace.

Example

ExampleExecFile demonstrates a simple embedding of the exprcore interpreter into a Go program.

package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/lab47/exprcore/exprcore"
)

func main() {
	const data = `
print(greeting + ", world")
print(repeat("one"))
print(repeat("mur", 2))
squares = [x*x for x in range(10)]
`

	// repeat(str, n=1) is a Go function called from exprcore.
	// It behaves like the 'string * int' operation.
	repeat := func(thread *exprcore.Thread, b *exprcore.Builtin, args exprcore.Tuple, kwargs []exprcore.Tuple) (exprcore.Value, error) {
		var s string
		var n int = 1
		if err := exprcore.UnpackArgs(b.Name(), args, kwargs, "s", &s, "n?", &n); err != nil {
			return nil, err
		}
		return exprcore.String(strings.Repeat(s, n)), nil
	}

	// The Thread defines the behavior of the built-in 'print' function.
	thread := &exprcore.Thread{
		Name:  "example",
		Print: func(_ *exprcore.Thread, msg string) { fmt.Println(msg) },
	}

	// This dictionary defines the pre-declared environment.
	predeclared := exprcore.StringDict{
		"greeting": exprcore.String("hello"),
		"repeat":   exprcore.NewBuiltin("repeat", repeat),
	}

	// Execute a program.
	globals, err := exprcore.ExecFile(thread, "apparent/filename.star", data, predeclared)
	if err != nil {
		if evalErr, ok := err.(*exprcore.EvalError); ok {
			log.Fatal(evalErr.Backtrace())
		}
		log.Fatal(err)
	}

	// Print the global environment.
	fmt.Println("\nGlobals:")
	for _, name := range globals.Keys() {
		v := globals[name]
		fmt.Printf("%s (%s) = %s\n", name, v.Type(), v.String())
	}

}
Output:

hello, world
one
murmur

Globals:
squares (list) = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

func (StringDict) Attr

func (d StringDict) Attr(name string) (Value, error)

func (StringDict) AttrNames

func (d StringDict) AttrNames() []string

func (StringDict) Freeze

func (d StringDict) Freeze()

func (StringDict) Has

func (d StringDict) Has(key string) bool

Has reports whether the dictionary contains the specified key.

func (StringDict) Keys

func (d StringDict) Keys() []string

Keys returns a new sorted slice of d's keys.

func (StringDict) String

func (d StringDict) String() string

type Thread

type Thread struct {
	// Name is an optional name that describes the thread, for debugging.
	Name string

	// Print is the client-supplied implementation of the exprcore
	// 'print' function. If nil, fmt.Fprintln(os.Stderr, msg) is
	// used instead.
	Print func(thread *Thread, msg string)

	// Load is the client-supplied implementation of module loading.
	// Repeated calls with the same module name must return the same
	// module environment or error.
	// The error message need not include the module name.
	//
	// See example_test.go for some example implementations of Load.
	Load func(thread *Thread, module string) (StringDict, error)

	Import func(thread *Thread, namespace, pkg string, args *Dict) (Value, error)

	Shell func(thread *Thread, parts []string) (Value, error)

	// A function to call before every call. if err is CallContinue, the
	// original call is performed, otherwise the value and error are returned.
	CallTrace func(thread *Thread, c Callable, args Tuple, kwargs []Tuple) (Value, error)
	// contains filtered or unexported fields
}

A Thread contains the state of a exprcore thread, such as its call stack and thread-local storage. The Thread is threaded throughout the evaluator.

func (*Thread) CallFrame

func (thread *Thread) CallFrame(depth int) CallFrame

CallFrame returns a copy of the specified frame of the callstack. It should only be used in built-ins called from exprcore code. Depth 0 means the frame of the built-in itself, 1 is its caller, and so on.

It is equivalent to CallStack().At(depth), but more efficient.

func (*Thread) CallStack

func (thread *Thread) CallStack() CallStack

CallStack returns a new slice containing the thread's stack of call frames.

func (*Thread) CallStackDepth

func (thread *Thread) CallStackDepth() int

CallStackDepth returns the number of frames in the current call stack.

func (*Thread) DebugFrame

func (thread *Thread) DebugFrame(depth int) DebugFrame

DebugFrame returns the debugger interface for the specified frame of the interpreter's call stack. Frame numbering is as for Thread.CallFrame.

This function is intended for use in debugging tools. Most applications should have no need for it; use CallFrame instead.

func (*Thread) Local

func (thread *Thread) Local(key string) interface{}

Local returns the thread-local value associated with the specified key.

func (*Thread) SetLocal

func (thread *Thread) SetLocal(key string, value interface{})

SetLocal sets the thread-local value associated with the specified key. It must not be called after execution begins.

type Tuple

type Tuple []Value

A Tuple represents a exprcore tuple value.

func (Tuple) CompareSameType

func (x Tuple) CompareSameType(op syntax.Token, y_ Value, depth int) (bool, error)

func (Tuple) Freeze

func (t Tuple) Freeze()

func (Tuple) Hash

func (t Tuple) Hash() (uint32, error)

func (Tuple) Index

func (t Tuple) Index(i int) Value

func (Tuple) Iterate

func (t Tuple) Iterate() Iterator

func (Tuple) Len

func (t Tuple) Len() int

func (Tuple) Slice

func (t Tuple) Slice(start, end, step int) Value

func (Tuple) String

func (t Tuple) String() string

func (Tuple) Truth

func (t Tuple) Truth() Bool

func (Tuple) Type

func (t Tuple) Type() string

type Unpacker

type Unpacker interface {
	Unpack(v Value) error
}

An Unpacker defines custom argument unpacking behavior. See UnpackArgs.

type Value

type Value interface {
	// String returns the string representation of the value.
	// exprcore string values are quoted as if by Python's repr.
	String() string

	// Type returns a short string describing the value's type.
	Type() string

	// Freeze causes the value, and all values transitively
	// reachable from it through collections and closures, to be
	// marked as frozen.  All subsequent mutations to the data
	// structure through this API will fail dynamically, making the
	// data structure immutable and safe for publishing to other
	// exprcore interpreters running concurrently.
	Freeze()

	// Truth returns the truth value of an object.
	Truth() Bool

	// Hash returns a function of x such that Equals(x, y) => Hash(x) == Hash(y).
	// Hash may fail if the value's type is not hashable, or if the value
	// contains a non-hashable value. The hash is used only by dictionaries and
	// is not exposed to the exprcore program.
	Hash() (uint32, error)
}

Value is a value in the exprcore interpreter.

func Binary

func Binary(op syntax.Token, x, y Value) (Value, error)

Binary applies a strict binary operator (not AND or OR) to its operands. For equality tests or ordered comparisons, use Compare instead.

func Call

func Call(thread *Thread, fn Value, args Tuple, kwargs []Tuple) (Value, error)

Call calls the function fn with the specified positional and keyword arguments.

func Eval

func Eval(thread *Thread, filename string, src interface{}, env StringDict) (Value, error)

Eval parses, resolves, and evaluates an expression within the specified (predeclared) environment.

Evaluation cannot mutate the environment dictionary itself, though it may modify variables reachable from the dictionary.

The filename and src parameters are as for syntax.Parse.

If Eval fails during evaluation, it returns an *EvalError containing a backtrace.

func EvalExpr

func EvalExpr(thread *Thread, expr syntax.Expr, env StringDict) (Value, error)

EvalExpr resolves and evaluates an expression within the specified (predeclared) environment. Evaluating a comma-separated list of expressions yields a tuple value.

Resolving an expression mutates it. Do not call EvalExpr more than once for the same expression.

Evaluation cannot mutate the environment dictionary itself, though it may modify variables reachable from the dictionary.

If Eval fails during evaluation, it returns an *EvalError containing a backtrace.

func Make

func Make(_ *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error)

Make is the implementation of a built-in function that instantiates an immutable struct from the specified keyword arguments.

An application can add 'struct' to the exprcore environment like so:

globals := exprcore.StringDict{
	"struct":  exprcore.NewBuiltin("struct", exprcorestruct.Make),
}

func Unary

func Unary(op syntax.Token, x Value) (Value, error)

Unary applies a unary operator (+, -, ~, not) to its operand.

Jump to

Keyboard shortcuts

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