exp

package
v0.0.0-...-9cd5b15 Latest Latest
Warning

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

Go to latest
Published: Feb 6, 2024 License: BSD-2-Clause Imports: 11 Imported by: 12

README

xelf/exp

Xelf is a simple but typed expression language with LISP-like parenthesis enclosed prefix calls. Expressions are one of Lit, Sym, Tag, Tupl or Call and implement the Exp interface.

  • literals values are JSON-compatible as defined by package lit and can also hold types and specs
  • symbols can contain alphanumeric identifiers and ASCII punctuations
  • tags allow str, sym and num keys ('str key':val, k:v) and a special short variant (flag;)
  • tuples are lists of expressions used for documents roots and form specs

A Prog is used to resolve and evaluate an expression using a root environment. Program resolution has two or more phases. In the first phases we call Resl methods to resolve all types. In the last phase we call Eval methods to evaluate an expression to a literal.

The program itself mostly manages type checking and otherwise calls out to environments and specs.

A Env configures the program evaluation by defining all symbols, importantly these symbols can resolve to specs that can be called and themselves create scoped environments that define symbols. Calls and symbols cache their environment.

A Spec is a func or form definition that resolves and evaluates calls. If the first element of a call does not resolve to a spec literal the program calls a dyn spec to allow syntax sugar. The dyn spec is evaluated from the root environment on init.

Specs have a declaration type. When we resolves a call spec we instantiate the spec declaration and call LayoutSpec to match and group all arguments to spec parameters.

Func specs have a strict and familiar parameter matching with support for named parameters and variadic last argument. Func parameters are evaluated before the call is evaluated, therefor funcs can also not change environment.

Form specs can mix in tupl parameters to match sequences of expressions, tags and even repeating groups of parameters. Forms can also use the exp type in their signature to signal the resolution not to resolve the argument and leave it to the spec. Form argument resolution and evaluation is responsibility of the spec.

The SpecBase type is a partial spec implementation that implements automatic argument resolution based on the type signature. Final implementations mostly need to handle call evaluation, but more involved specs can implement custom call resolution too, for example to set nested scopes.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrDefer = fmt.Errorf("deferred resolution")

ErrDefer is a marker error used to indicate a deferred resolution and not a failure per-se. The user can errors.Is(err, ErrDefer) and resume program resolution with more context provided.

View Source
var ErrSymNotFound = fmt.Errorf("sym not found")

ErrSymNotFound is an error that indicates that a symbol was not found in the environment

Functions

func DotPath

func DotPath(p cor.Path) (cor.Path, bool)

DotPath returns whether p is a dot path or returns p with a leading dot segment removed.

func LookupKey

func LookupKey(env Env, k string) (lit.Val, error)

func LookupMod

func LookupMod(p *Prog, qual string, rest cor.Path) (lit.Val, error)

func LookupType

func LookupType(env Env) typ.Lookup

func SelectLookup

func SelectLookup(v lit.Val, p cor.Path, eval bool) (lit.Val, error)

SelectLookup reads path and returns the selected literal from l or an error. If eval is false we attempt to at least resolve the intended type if no value was found.

func SigArgs

func SigArgs(sig typ.Type) []typ.Param

func SigRes

func SigRes(sig typ.Type) *typ.Param

func SplitQualifier

func SplitQualifier(k string) (q, _ string)

Types

type Builtins

type Builtins map[string]Spec

Builtins is a root environment to resolve symbols to builtin specs and at last as types.

func (Builtins) Lookup

func (e Builtins) Lookup(s *Sym, p cor.Path, eval bool) (lit.Val, error)

func (Builtins) Parent

func (e Builtins) Parent() Env

type Call

type Call struct {
	Sig  typ.Type
	Spec Spec
	Args []Exp
	Env  Env
	Src  ast.Src
}

Call is an executable expression that uses a spec to evaluate to a literal. It caches the resolved spec and environment.

func (*Call) Clone

func (c *Call) Clone() Exp

func (*Call) Print

func (c *Call) Print(p *bfr.P) error

func (*Call) Source

func (c *Call) Source() ast.Src

func (*Call) String

func (c *Call) String() string

func (*Call) Type

func (c *Call) Type() typ.Type

type Dyn

type Dyn func(*Prog, Env, *Call, typ.Type) error

func DefaultDyn

func DefaultDyn(env Env) Dyn

type Env

type Env interface {
	// Parent returns the parent environment or nil.
	Parent() Env

	// Lookup resolves a symbol path and returns the result, an error or nothing.
	// We always update the symbol and return resolved values.
	// If eval is false the symbol resolves, but the value does not, we return nothing.
	// If the value is not resolved and eval is true we return an error.
	Lookup(s *Sym, path cor.Path, eval bool) (lit.Val, error)
}

Env is a scoped context to resolve symbols. Envs configure most of the program resolution.

type Exp

type Exp interface {
	Type() typ.Type
	Source() ast.Src
	String() string
	Print(*bfr.P) error
	Clone() Exp
}

Exp is the common interface of all expressions with kind, type and source info.

func LayoutForm

func LayoutForm(sig typ.Type, els []Exp) ([]Exp, error)

func LayoutFunc

func LayoutFunc(sig typ.Type, els []Exp) ([]Exp, error)

func LayoutSpec

func LayoutSpec(sig typ.Type, els []Exp) ([]Exp, error)

func Parse

func Parse(str string) (Exp, error)

Parse parses str and returns an expression or an error.

func ParseAll

func ParseAll(as []ast.Ast) (Exp, error)

func ParseAst

func ParseAst(a ast.Ast) (Exp, error)

ParseAst parses a as expression and returns it or an error.

func Read

func Read(r io.Reader, name string) (Exp, error)

Read parses named reader r and returns an expression or an error.

type File

type File struct {
	// URL is the resource locator for this input, it should be empty or conform to net/url.
	// It usually is a simple file path, but could point into a zip file served on the web.
	URL string

	// Refs contains all declared and used modules for this file.
	Refs ModRefs
}

File is a simple representation of any xelf input that store information about modules.

func (*File) AddRefs

func (f *File) AddRefs(refs ...ModRef) error

type Lit

type Lit struct {
	Val lit.Val
	Src ast.Src
}

Lit is a literal expression with a literal value, which may include a type or spec.

func LitSrc

func LitSrc(v lit.Val, s ast.Src) *Lit

func LitVal

func LitVal(v lit.Val) *Lit

func (*Lit) Clone

func (a *Lit) Clone() Exp

func (*Lit) Print

func (a *Lit) Print(p *bfr.P) error

func (*Lit) Source

func (a *Lit) Source() ast.Src

func (*Lit) String

func (a *Lit) String() string

func (*Lit) Type

func (a *Lit) Type() typ.Type

func (*Lit) Value

func (a *Lit) Value() lit.Val

type Mod

type Mod struct {
	// File points to the original source file of this module.
	File *File

	// Name is the declare module name.
	Name string

	// Decl holds the exported module declarations, that are copied for each program.
	Decl *lit.Obj
}

Mod is a simple representation of a module.

type ModRef

type ModRef struct {
	Alias string
	Path  string
	Pub   bool
	*Mod
}

ModRef represent a module reference with a possible alias the original import path.

func (ModRef) Key

func (ref ModRef) Key() string

Key returns the alias or module name.

type ModRefs

type ModRefs []ModRef

func (ModRefs) Find

func (ms ModRefs) Find(k string) *ModRef

type Prog

type Prog struct {
	Ctx  context.Context
	Root Env
	Sys  *typ.Sys
	Reg  lit.Regs
	Arg  lit.Val

	File File
	// Files collects all external files loaded by the program
	Files map[string]*File
	// Birth holds the uri for actively loading files to break recursive loads
	Birth map[string]struct{}

	Dyn Dyn
	// contains filtered or unexported fields
}

Prog is the entry context to resolve an expression in an environment. Programs are bound to their expression and cannot be reused.

func FindProg

func FindProg(env Env) *Prog

func NewProg

func NewProg(env Env, args ...interface{}) *Prog

NewProg returns a new program using the given registry, environment and expression. The registry argument can be nil, a new registry will be used by default.

func (*Prog) Eval

func (p *Prog) Eval(env Env, e Exp) (_ lit.Val, err error)

Eval evaluates a resolved expression and returns a value or an error.

func (*Prog) EvalArgs

func (p *Prog) EvalArgs(c *Call) (lit.Vals, error)

EvalArgs evaluates resolved call arguments and returns the result or an error. This is a convenience method for the most basic needs of many spec implementations.

func (*Prog) Lookup

func (p *Prog) Lookup(s *Sym, pp cor.Path, eval bool) (res lit.Val, err error)

func (*Prog) NextFnID

func (p *Prog) NextFnID() uint

NextFnID returns a new number to identify an anonymous function.

func (*Prog) Parent

func (p *Prog) Parent() Env

func (*Prog) Resl

func (p *Prog) Resl(env Env, e Exp, h typ.Type) (Exp, error)

Resl resolves an expression using a type hint and returns the result or an error.

func (*Prog) Run

func (p *Prog) Run(x Exp, arg lit.Val) (_ lit.Val, err error)

Run resolves and evaluates the input expression and returns the result or an error.

func (*Prog) RunStr

func (p *Prog) RunStr(str string, arg lit.Val) (lit.Val, error)

RunStr resolves and evaluates the input string and returns the result or an error.

type Spec

type Spec interface {
	Type() typ.Type

	// Resl resolves a call using a type hint and returns the result or an error.
	// The first call to Resl should setup the environment for call c.
	Resl(p *Prog, env Env, c *Call, hint typ.Type) (Exp, error)

	// Eval evaluates a resolved call and returns a value or an error.
	Eval(p *Prog, c *Call) (lit.Val, error)
}

Spec is a func or form specification used to resolve calls.

type SpecBase

type SpecBase struct{ Decl typ.Type }

SpecBase is partial base definition for spec implementations. Implementations only need embed this type and declare the eval method.

func MustSpecBase

func MustSpecBase(sig string) SpecBase

func (*SpecBase) Resl

func (s *SpecBase) Resl(p *Prog, env Env, c *Call, h typ.Type) (Exp, error)

func (*SpecBase) Type

func (s *SpecBase) Type() typ.Type

type SpecRef

type SpecRef struct {
	Spec Spec
	Decl typ.Type
}

SpecRef can wrap any spec with a new type and can represent null and unresolved specs.

func NewSpecRef

func NewSpecRef(s Spec) *SpecRef

func UnwrapSpec

func UnwrapSpec(v interface{}) (s *SpecRef)

func (*SpecRef) As

func (s *SpecRef) As(t typ.Type) (lit.Val, error)

func (*SpecRef) Assign

func (s *SpecRef) Assign(val lit.Val) error

func (*SpecRef) Eval

func (s *SpecRef) Eval(p *Prog, c *Call) (lit.Val, error)

func (*SpecRef) MarshalJSON

func (s *SpecRef) MarshalJSON() ([]byte, error)

func (*SpecRef) Mut

func (s *SpecRef) Mut() lit.Mut

func (*SpecRef) New

func (s *SpecRef) New() lit.Mut

func (*SpecRef) Nil

func (s *SpecRef) Nil() bool

func (*SpecRef) Parse

func (s *SpecRef) Parse(a ast.Ast) (err error)

func (*SpecRef) Print

func (s *SpecRef) Print(p *bfr.P) error

func (*SpecRef) Ptr

func (s *SpecRef) Ptr() interface{}

func (*SpecRef) Resl

func (s *SpecRef) Resl(p *Prog, env Env, c *Call, hint typ.Type) (Exp, error)

func (*SpecRef) String

func (s *SpecRef) String() string

func (*SpecRef) Type

func (s *SpecRef) Type() typ.Type

func (*SpecRef) Value

func (s *SpecRef) Value() lit.Val

func (*SpecRef) Zero

func (s *SpecRef) Zero() bool

type Sym

type Sym struct {
	Res  typ.Type
	Sym  string
	Src  ast.Src
	Env  Env
	Path cor.Path
}

Sym is a symbol expression which caches the resolving environment and a relative name.

func (*Sym) Clone

func (s *Sym) Clone() Exp

func (*Sym) Print

func (s *Sym) Print(p *bfr.P) error

func (*Sym) Source

func (s *Sym) Source() ast.Src

func (*Sym) String

func (s *Sym) String() string

func (*Sym) Type

func (s *Sym) Type() typ.Type

func (*Sym) Update

func (s *Sym) Update(t typ.Type, env Env, p cor.Path)

type Tag

type Tag struct {
	Tag string
	Exp Exp
	Src ast.Src
}

Tag is a named quasi expression that is resolved by its parent call.

func (*Tag) Clone

func (t *Tag) Clone() Exp

func (*Tag) Print

func (t *Tag) Print(p *bfr.P) error

func (*Tag) Source

func (t *Tag) Source() ast.Src

func (*Tag) String

func (t *Tag) String() string

func (*Tag) Type

func (t *Tag) Type() typ.Type

type Tupl

type Tupl struct {
	Res typ.Type
	Els []Exp
	Src ast.Src
}

Tupl is a quasi multi-expression that is resolved by its parent call or a program.

func (*Tupl) Clone

func (t *Tupl) Clone() Exp

func (*Tupl) Print

func (t *Tupl) Print(p *bfr.P) error

func (*Tupl) Source

func (t *Tupl) Source() ast.Src

func (*Tupl) String

func (t *Tupl) String() string

func (*Tupl) Type

func (t *Tupl) Type() typ.Type

Jump to

Keyboard shortcuts

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