sxeval

package
v0.0.0-...-ec4fcc6 Latest Latest
Warning

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

Go to latest
Published: May 13, 2024 License: EUPL-1.2 Imports: 9 Imported by: 1

README

sxeval - an evaluator for symbolic expressions

Symbolic expressions may be interpreted, i.e. evaluated.

Most sx.Objects evaluate to themselves.

sx.Symbols are resolved in an sxeval.Environment to a bound value. If no bound value is found, some actions are taken. See below for details.

A non-empty list is treated differently: its first object must evaluate to a "callable" object, i.e. a function. The other objects of the list are evaluated recursively and are treated as arguments for that function.

The first object of a list may alternatively evaluate to a "syntax" object, also a function. The function is called with the other objects of the list as its arguments. The result of the function call, typically a list, is then evaluated too. This allows some kind of meta-evaluation.

"Callable" and "syntax" objects are defined in the package sxbuiltins.

Evaluation works in three steps:

  1. The object is parsed according to the evaluation rules, resulting in an "expression" object (sxeval.Expr).
  2. Expression objects may be "reworked", into possibly simpler expression objects. For example, if a symbols's value cannot be changed, the symbol lookup can be replaced with its value.
  3. The expression is computed with respect to a given environment, resulting in an object.

This separation allowed to pre-compute the structure of an object, resulting in possibly faster execution time or less memory to store. Parsing an reworking can be done in advance, while computing can be done much later.

To make the steps of evaluation easier to handle, sxeval defines an "environment" type (sxeval.Environment) that provides appropriate functions. Its central attribute is the current "binding".

sxeval.Bindings are effectively just a mapping of sx.Symbols to an sx.Object. A sx.Symbol is bound to a sx.Object.

The are two types of bindings: a constant binding does not allow to update the sx.Object that is bound to the sx.Symbol. A variable binding allows this update.

sxeval.Bindings form a hierarchy: all but one have a parent binding. This allows to overwrite constant bindings somehow: create a child parent and bind the sx.Symbol to another sx.Object, and evaluate a sx.Object in the new child binding.

Resolving a sx.Symbol works as follows: when a sx.Symbol is looked up in a given environment, and it is not bound in that environments binding, the sx.Symbol is resolved in the parent binding.

Of course, there is a binding that does not have a parent binding: the root binding. If a sx.Symbol is not bound in the root binding, the lookup operation fails.

Documentation

Overview

Package sxeval allows to evaluate s-expressions. Evaluation is splitted into parsing that s-expression and executing the result of the parsed expression. This is done to reduce syntax checks.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoArgs = errors.New("no arguments given")

ErrNoArgs signals that no arguments were given.

View Source
var NilExpr = nilExpr{}

NilExpr returns always Nil

Functions

func AssertPure

func AssertPure(sx.Vector) bool

AssertPure is a TestPure function that alsways returns true.

func PrintExprs

func PrintExprs(w io.Writer, exprs []Expr) (int, error)

PrintExprs is a helper method to implement Expr.Print.

Types

type Binding

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

Binding is a binding based on maps.

func GetBinding

func GetBinding(obj sx.Object) (*Binding, bool)

GetBinding returns the object as a binding, if possible.

func MakeRootBinding

func MakeRootBinding(sizeHint int) *Binding

MakeRootBinding creates a new root binding.

func (*Binding) Bind

func (b *Binding) Bind(sym *sx.Symbol, obj sx.Object) error

Bind creates a local mapping with a given symbol and object.

A previous mapping will be overwritten.

func (*Binding) BindBuiltin

func (b *Binding) BindBuiltin(bi *Builtin) error

BindBuiltin binds the given builtin with its given name.

func (*Binding) BindSpecial

func (b *Binding) BindSpecial(syn *Special) error

func (*Binding) Bindings

func (b *Binding) Bindings() *sx.Pair

Bindings returns all bindings as an a-list in some random order.

func (*Binding) Freeze

func (b *Binding) Freeze()

Freeze sets the binding in a read-only state.

func (*Binding) GoString

func (b *Binding) GoString() string

func (*Binding) IsAtom

func (b *Binding) IsAtom() bool

func (*Binding) IsEqual

func (b *Binding) IsEqual(other sx.Object) bool

func (*Binding) IsFrozen

func (b *Binding) IsFrozen() bool

IsFrozen returns true if binding is frozen.

func (*Binding) IsNil

func (b *Binding) IsNil() bool

func (*Binding) Lookup

func (b *Binding) Lookup(sym *sx.Symbol) (sx.Object, bool)

Lookup will search for a local binding of the given symbol. If not found, the search will *not* be continued in the parent binding. Use the global `Resolve` function, if you want a search up to the parent.

func (*Binding) LookupN

func (b *Binding) LookupN(sym *sx.Symbol, n int) (sx.Object, bool)

LookupN will lookup the symbol in the N-th parent.

func (*Binding) MakeChildBinding

func (b *Binding) MakeChildBinding(name string, sizeHint int) *Binding

MakeChildBinding creates a new binding with a given parent.

func (*Binding) Name

func (b *Binding) Name() string

Name returns the local name of this binding.

func (*Binding) Parent

func (b *Binding) Parent() *Binding

Parent returns the parent binding.

func (*Binding) Resolve

func (b *Binding) Resolve(sym *sx.Symbol) (sx.Object, bool)

Resolve a symbol in a binding and all of its parent bindings.

func (*Binding) ResolveN

func (b *Binding) ResolveN(sym *sx.Symbol, n int) (sx.Object, bool)

ResolveN resolves a symbol in the N-th parent binding and all of its parent bindings.

func (*Binding) String

func (b *Binding) String() string

func (*Binding) Symbols

func (b *Binding) Symbols() []*sx.Symbol

Symbols returns all bound symbols, sorted by its GoString.

type Builtin

type Builtin struct {
	// The canonical Name of the builtin
	Name string

	// Minimum and maximum arity. If MaxArity < 0, maximum arity is unlimited
	MinArity, MaxArity int16

	// Test builtin to be independent of the environment and does not produce some side effect
	TestPure func(sx.Vector) bool

	// The actual builtin function, with no argument
	Fn0 func(*Environment) (sx.Object, error)

	// The actual builtin function, with one argument
	Fn1 func(*Environment, sx.Object) (sx.Object, error)

	// The actual builtin function, with two arguments
	Fn2 func(*Environment, sx.Object, sx.Object) (sx.Object, error)

	// The actual builtin function, with any number of arguments
	Fn func(*Environment, sx.Vector) (sx.Object, error)

	// Do not add a CallError
	NoCallError bool
}

Builtin is the type for normal predefined functions.

func (*Builtin) Call

func (b *Builtin) Call(env *Environment, args sx.Vector) (sx.Object, error)

Call the builtin function with the given environment and arguments.

func (*Builtin) Call0

func (b *Builtin) Call0(env *Environment) (sx.Object, error)

Call0 the builtin function with the given environment and no arguments.

func (*Builtin) Call1

func (b *Builtin) Call1(env *Environment, arg sx.Object) (sx.Object, error)

Call1 the builtin function with the given environment and one argument.

func (*Builtin) Call2

func (b *Builtin) Call2(env *Environment, arg0, arg1 sx.Object) (sx.Object, error)

Call2 the builtin function with the given environment and two arguments.

func (*Builtin) GoString

func (b *Builtin) GoString() string

GoString returns the go string representation.

func (*Builtin) IsAtom

func (b *Builtin) IsAtom() bool

IsAtom returns true iff the object is an object that is not further decomposable.

func (*Builtin) IsEqual

func (b *Builtin) IsEqual(other sx.Object) bool

IsEqual compare two objects for deep equality.

func (*Builtin) IsNil

func (b *Builtin) IsNil() bool

IsNil checks if the concrete object is nil.

func (*Builtin) IsPure

func (b *Builtin) IsPure(objs sx.Vector) bool

IsPure returns true if builtin is a pure function.

func (*Builtin) String

func (b *Builtin) String() string

String returns the string representation.

type BuiltinCallExpr

type BuiltinCallExpr struct {
	Proc *Builtin
	Args []Expr
}

BuiltinCallExpr calls a builtin and returns the resulting object. It is an optimization of `CallExpr.`

func (*BuiltinCallExpr) Compute

func (bce *BuiltinCallExpr) Compute(env *Environment) (sx.Object, error)

func (*BuiltinCallExpr) Improve

func (bce *BuiltinCallExpr) Improve(re *ReworkEnvironment) Expr

func (*BuiltinCallExpr) Print

func (bce *BuiltinCallExpr) Print(w io.Writer) (int, error)

func (*BuiltinCallExpr) String

func (bce *BuiltinCallExpr) String() string

func (*BuiltinCallExpr) Unparse

func (bce *BuiltinCallExpr) Unparse() sx.Object

type CallError

type CallError struct {
	Name string
	Err  error
}

CallError encapsulate an error that occured during a call.

func (CallError) Error

func (e CallError) Error() string

func (CallError) Unwrap

func (e CallError) Unwrap() error

type CallExpr

type CallExpr struct {
	Proc Expr
	Args []Expr
}

CallExpr calls a procedure and returns the resulting objects.

func (*CallExpr) Compute

func (ce *CallExpr) Compute(env *Environment) (sx.Object, error)

func (*CallExpr) Improve

func (ce *CallExpr) Improve(re *ReworkEnvironment) Expr

func (*CallExpr) Print

func (ce *CallExpr) Print(w io.Writer) (int, error)

func (*CallExpr) String

func (ce *CallExpr) String() string

func (*CallExpr) Unparse

func (ce *CallExpr) Unparse() sx.Object

type Callable

type Callable interface {
	sx.Object

	// IsPure checks if the callable is independent of a full environment and
	// does not produce any side effects.
	IsPure(sx.Vector) bool

	// Call0 with no argument in given environment.
	Call0(*Environment) (sx.Object, error)

	// Call1 with one argument in given environment.
	Call1(*Environment, sx.Object) (sx.Object, error)

	// Call2 with two arguments in given environment.
	Call2(*Environment, sx.Object, sx.Object) (sx.Object, error)

	// Call the value with the given args in the given environment.
	Call(*Environment, sx.Vector) (sx.Object, error)
}

Callable is an sx.Object which can be called for evaluation.

func GetCallable

func GetCallable(obj sx.Object) (Callable, bool)

GetCallable returns the object as a Callable, if possible.

type ConstObjectExpr

type ConstObjectExpr interface {
	ConstObject() sx.Object
}

ConstObjectExpr is an Expr that results in a specific, constant sx.Object.

func GetConstExpr

func GetConstExpr(expr Expr) (ConstObjectExpr, bool)

GetConstExpr returns the Expr as a ConstObjectExpr, if possible.

type Environment

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

Environment is a runtime object of the current computing environment.

func MakeExecutionEnvironment

func MakeExecutionEnvironment(bind *Binding) *Environment

MakeExecutionEnvironment creates an environment for later execution of an expression.

func (*Environment) Bind

func (env *Environment) Bind(sym *sx.Symbol, obj sx.Object) error

func (*Environment) Binding

func (env *Environment) Binding() *Binding

func (*Environment) Call

func (env *Environment) Call(fn Callable, args sx.Vector) (res sx.Object, err error)

Call the given Callable with the arguments.

func (*Environment) Compile

func (env *Environment) Compile(obj sx.Object) (Expr, error)

Compile the given object and return the reworked expression.

func (*Environment) Eval

func (env *Environment) Eval(obj sx.Object) (sx.Object, error)

Eval parses the given object and runs it in the environment.

func (*Environment) Execute

func (env *Environment) Execute(expr Expr) (res sx.Object, err error)

Execute the given expression.

func (*Environment) ExecuteTCO

func (env *Environment) ExecuteTCO(expr Expr) (sx.Object, error)

ExecuteTCO is called when the expression should be executed at last position, aka as tail call order.

func (*Environment) FindBinding

func (env *Environment) FindBinding(sym *sx.Symbol) *Binding

func (*Environment) Lookup

func (env *Environment) Lookup(sym *sx.Symbol) (sx.Object, bool)

func (*Environment) LookupNWithError

func (env *Environment) LookupNWithError(sym *sx.Symbol, n int) (sx.Object, error)

func (*Environment) MakeNotBoundError

func (env *Environment) MakeNotBoundError(sym *sx.Symbol) NotBoundError

func (*Environment) MakeParseEnvironment

func (env *Environment) MakeParseEnvironment() *ParseEnvironment

func (*Environment) MakeReworkEnvironment

func (env *Environment) MakeReworkEnvironment() *ReworkEnvironment

func (*Environment) NewLexicalEnvironment

func (env *Environment) NewLexicalEnvironment(parent *Binding, name string, numBindings int) *Environment

func (*Environment) Parse

func (env *Environment) Parse(obj sx.Object) (Expr, error)

Parse the given object.

func (*Environment) RebindExecutionEnvironment

func (env *Environment) RebindExecutionEnvironment(bind *Binding) *Environment

RebindExecutionEnvironment clones the original environment, but uses the given binding.

func (*Environment) Resolve

func (env *Environment) Resolve(sym *sx.Symbol) (sx.Object, bool)

func (*Environment) ResolveNWithError

func (env *Environment) ResolveNWithError(sym *sx.Symbol, skip int) (sx.Object, error)

func (*Environment) ResolveUnboundWithError

func (env *Environment) ResolveUnboundWithError(sym *sx.Symbol) (sx.Object, error)

func (*Environment) Rework

func (env *Environment) Rework(expr Expr) Expr

Rework the given expression.

func (*Environment) Run

func (env *Environment) Run(expr Expr) (sx.Object, error)

Run the given expression.

func (*Environment) SetExecutor

func (env *Environment) SetExecutor(observe ExecuteObserver) *Environment

SetExecutor sets the given executor.

func (*Environment) SetParseObserver

func (env *Environment) SetParseObserver(observe ParseObserver) *Environment

SetParseObserver sets the given parsing observer.

func (*Environment) SetReworkObserver

func (env *Environment) SetReworkObserver(observe ReworkObserver) *Environment

SetReworkObserver sets the given rework observer.

func (*Environment) String

func (env *Environment) String() string

type EnvironmentExpr

type EnvironmentExpr struct {
	Env  *Environment
	Expr Expr
}

type ErrBindingFrozen

type ErrBindingFrozen struct{ Binding *Binding }

ErrBindingFrozen is returned when trying to update a frozen binding.

func (ErrBindingFrozen) Error

func (err ErrBindingFrozen) Error() string

type ExecuteError

type ExecuteError struct {
	Stack []EnvironmentExpr
	// contains filtered or unexported fields
}

func (ExecuteError) Error

func (ee ExecuteError) Error() string

func (ExecuteError) PrintStack

func (ee ExecuteError) PrintStack(w io.Writer, prefix string, logger *slog.Logger, logmsg string)

func (ExecuteError) Unwrap

func (ee ExecuteError) Unwrap() error

type ExecuteObserver

type ExecuteObserver interface {
	// BeforeExecution is called immediate before the given expression is executed.
	// The observer may change the expression or abort execution with an error.
	BeforeExecution(*Environment, Expr) (Expr, error)

	// AfterExecution is called immediate after the given expression was executed,
	// resulting in an `sx.Object` and an error.
	AfterExecution(*Environment, Expr, sx.Object, error)
}

ExecuteObserver observes the execution of expressions.

type Expr

type Expr interface {
	// Unparse the expression as an sx.Object
	Unparse() sx.Object

	// Improve the expressions to a possible simpler one.
	Improve(*ReworkEnvironment) Expr

	// Compute the expression in a frame and return the result.
	// It may have side-effects, on the given environment, or on the
	// general environment of the system.
	Compute(*Environment) (sx.Object, error)

	// Print the expression on the given writer.
	Print(io.Writer) (int, error)
}

Expr are values that are computed for evaluation in an environment.

type ExprObj

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

ExprObj encapsulates an Expr in an sx.Object.

func GetExprObj

func GetExprObj(obj sx.Object) (*ExprObj, bool)

GetExprObj returns the object as a expression object, if possible.

func MakeExprObj

func MakeExprObj(expr Expr) *ExprObj

MakeExprObj creates an ExprObj from an Expr.

func (*ExprObj) GetExpr

func (eo *ExprObj) GetExpr() Expr

func (*ExprObj) GoString

func (eo *ExprObj) GoString() string

func (*ExprObj) IsAtom

func (*ExprObj) IsAtom() bool

func (*ExprObj) IsEqual

func (eo *ExprObj) IsEqual(other sx.Object) bool

func (*ExprObj) IsNil

func (eo *ExprObj) IsNil() bool

func (*ExprObj) String

func (eo *ExprObj) String() string

type LookupSymbolExpr

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

LookupSymbolExpr is a special UnboundSymbolExpr that gives an indication about the nesting level of `Binding`s, where the symbol will be bound.

func (*LookupSymbolExpr) Compute

func (lse *LookupSymbolExpr) Compute(env *Environment) (sx.Object, error)

func (*LookupSymbolExpr) GetLevel

func (lse *LookupSymbolExpr) GetLevel() int

func (*LookupSymbolExpr) GetSymbol

func (lse *LookupSymbolExpr) GetSymbol() *sx.Symbol

func (*LookupSymbolExpr) Improve

func (lse *LookupSymbolExpr) Improve(*ReworkEnvironment) Expr

func (LookupSymbolExpr) Print

func (lse LookupSymbolExpr) Print(w io.Writer) (int, error)

func (*LookupSymbolExpr) Unparse

func (lse *LookupSymbolExpr) Unparse() sx.Object

type NotBoundError

type NotBoundError struct {
	Binding *Binding
	Sym     *sx.Symbol
}

NotBoundError signals that a symbol was not found in a binding.

func (NotBoundError) Error

func (e NotBoundError) Error() string

type NotCallableError

type NotCallableError struct {
	Obj sx.Object
}

NotCallableError signals that a value cannot be called when it must be called.

func (NotCallableError) Error

func (e NotCallableError) Error() string

func (NotCallableError) String

func (e NotCallableError) String() string

type ObjExpr

type ObjExpr struct {
	Obj sx.Object
}

ObjExpr returns the stored object.

func (ObjExpr) Compute

func (oe ObjExpr) Compute(*Environment) (sx.Object, error)

func (ObjExpr) ConstObject

func (oe ObjExpr) ConstObject() sx.Object

func (ObjExpr) Improve

func (oe ObjExpr) Improve(re *ReworkEnvironment) Expr

func (ObjExpr) Print

func (oe ObjExpr) Print(w io.Writer) (int, error)

func (ObjExpr) Unparse

func (oe ObjExpr) Unparse() sx.Object

type ParseEnvironment

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

ParseEnvironment is a parsing environment.

func (*ParseEnvironment) Bind

func (pf *ParseEnvironment) Bind(sym *sx.Symbol, obj sx.Object) error

func (*ParseEnvironment) Binding

func (pf *ParseEnvironment) Binding() *Binding

func (*ParseEnvironment) MakeChildFrame

func (pf *ParseEnvironment) MakeChildFrame(name string, baseSize int) *ParseEnvironment

func (*ParseEnvironment) Parse

func (pf *ParseEnvironment) Parse(form sx.Object) (expr Expr, err error)

func (*ParseEnvironment) ParseAgain

func (pf *ParseEnvironment) ParseAgain(form sx.Object) error

func (*ParseEnvironment) Resolve

func (pf *ParseEnvironment) Resolve(sym *sx.Symbol) (sx.Object, bool)

type ParseObserver

type ParseObserver interface {
	// BeforeParse is called immediate before the given form is parsed.
	// The observer may change the form and abort the parse with an error.
	BeforeParse(*ParseEnvironment, sx.Object) (sx.Object, error)

	// AfterParse is called immediate after the given form was parsed to the expression.
	AfterParse(*ParseEnvironment, sx.Object, Expr, error)
}

ParseObserver monitors the parsing process.

type ResolveSymbolExpr

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

ResolveSymbolExpr is a special `UnboundSymbolExpr` that must be resolved in the base environment. Traversal through all nested lexical bindings is not needed.

func (ResolveSymbolExpr) Compute

func (use ResolveSymbolExpr) Compute(env *Environment) (sx.Object, error)

func (ResolveSymbolExpr) GetSymbol

func (rse ResolveSymbolExpr) GetSymbol() *sx.Symbol

func (ResolveSymbolExpr) Improve

func (rse ResolveSymbolExpr) Improve(re *ReworkEnvironment) Expr

func (ResolveSymbolExpr) Print

func (use ResolveSymbolExpr) Print(w io.Writer) (int, error)

func (ResolveSymbolExpr) Unparse

func (rse ResolveSymbolExpr) Unparse() sx.Object

type ReworkEnvironment

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

ReworkEnvironment guides the Expr.Rework operation.

func (*ReworkEnvironment) Bind

func (re *ReworkEnvironment) Bind(sym *sx.Symbol) error

Bind the undefined value to the symbol in the current environment.

func (*ReworkEnvironment) Binding

func (re *ReworkEnvironment) Binding() *Binding

Binding returns the binding of this environment.

func (*ReworkEnvironment) Call

func (re *ReworkEnvironment) Call(fn Callable, args sx.Vector) (sx.Object, error)

Call a function for constant folding.

It is only called, if no full execution environment is needed, only a binding.

func (*ReworkEnvironment) Height

func (re *ReworkEnvironment) Height() int

Height returns the difference between the acual and the base height.

func (*ReworkEnvironment) MakeChildEnvironment

func (re *ReworkEnvironment) MakeChildEnvironment(name string, baseSize int) *ReworkEnvironment

MakeChildEnvironment creates a subordinate rework environment with a new binding.

func (*ReworkEnvironment) Resolve

func (re *ReworkEnvironment) Resolve(sym *sx.Symbol) (sx.Object, int, bool)

Resolve the symbol into an object, and return the binding depth plus an indication about the const-ness of the value. If the symbol could not be resolved, depth has the value of `math.MinInt`. If the symbol was found in the base environment, depth is set to -1, to indicate a possible unbound situation.

func (*ReworkEnvironment) Rework

func (re *ReworkEnvironment) Rework(expr Expr) Expr

Rework the given expression. Do not call `expr.Rework()` directly.

type ReworkObserver

type ReworkObserver interface {
	// BeforeRework is called immediate before the given expression is reworked.
	BeforeRework(*ReworkEnvironment, Expr) Expr

	// AfterRework is called after the given expression was reworked to a
	// possibly simpler one.
	AfterRework(*ReworkEnvironment, Expr, Expr)
}

ReworkObserver monitors the inner workings of the rework process.

type Special

type Special struct {
	Name string
	Fn   func(*ParseEnvironment, *sx.Pair) (Expr, error)
}

Special represents all predefined syntax constructing functions implemented in Go.

func (*Special) GoString

func (sp *Special) GoString() string

func (*Special) IsAtom

func (sp *Special) IsAtom() bool

func (*Special) IsEqual

func (sp *Special) IsEqual(other sx.Object) bool

func (*Special) IsNil

func (sp *Special) IsNil() bool

func (*Special) Parse

func (sp *Special) Parse(pf *ParseEnvironment, args *sx.Pair) (Expr, error)

Parse the args by calling the syntax function.

func (*Special) String

func (sp *Special) String() string

type SymbolExpr

type SymbolExpr interface {
	Expr
	GetSymbol() *sx.Symbol
}

SymbolExpr is the common interface of Expr that handles symbols.

type Syntax

type Syntax interface {
	// Parse the args.
	Parse(pf *ParseEnvironment, args *sx.Pair) (Expr, error)
}

Syntax is a form that produces an expression by parsing.

It is not the same as interface `Parser`, because the second parameter is a pair.

func GetSyntax

func GetSyntax(obj sx.Object) (Syntax, bool)

GetSyntax returns the object as a syntax value, if possible.

type UnboundSymbolExpr

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

UnboundSymbolExpr resolves the given symbol in an environment and returns its value.

func (UnboundSymbolExpr) Compute

func (use UnboundSymbolExpr) Compute(env *Environment) (sx.Object, error)

func (UnboundSymbolExpr) GetSymbol

func (use UnboundSymbolExpr) GetSymbol() *sx.Symbol

func (UnboundSymbolExpr) Improve

func (use UnboundSymbolExpr) Improve(re *ReworkEnvironment) Expr

func (UnboundSymbolExpr) Print

func (use UnboundSymbolExpr) Print(w io.Writer) (int, error)

func (UnboundSymbolExpr) Unparse

func (use UnboundSymbolExpr) Unparse() sx.Object

Jump to

Keyboard shortcuts

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