exp

package
v0.0.0-...-7e8a755 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2020 License: BSD-2-Clause Imports: 8 Imported by: 9

Documentation

Overview

Package exp is a simple and extensible expression language, built on xelf types and literals. It is meant to be used as a base for domain specific languages for a variety of tasks.

Language elements implement the interface El and are pointer of the following types:

Atom  for literals, including type literals
Sym   for unresolved symbols
Dyn   for unresolved expressions
Call  for expressions with a resolved form or func specification
Named for special tag syntax elements used in call arguments

Parse reads a tree and returns atoms, symbols, named or dynamic expressions. Literals and type symbols as well as type expressions are parsed as atoms. Tag symbols associate to the neighoring elements.

Prog is a program with a type context used to resolve or evaluate elements.

Resl resolves symbol types and dyn expressions to calls or atoms.

The resolution uses the spec signature and is automatic for all function specs and most form specs.

Dynamic expressions are resolved to call expressions. Dynamic expressions starting with a spec use that spec directly, starting with a literal or type lookup a built-in spec. Language extensions can change the dynamic lookup in the program context.

Eval evaluates elements resulting in an atom or partially resolved element.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrRedefine is returned when the symbol is redefined in the same scope.
	ErrRedefine = cor.StrError("redefined symbol")
)
View Source
var ErrUnres = cor.StrError("unresolved")

ErrUnres is returned by a resolver if the result is unresolved, but otherwise valid.

View Source
var ErrVoid = cor.StrError("void")
View Source
var SkipTraverse = cor.StrError("skip traverse")

Functions

func DefaultDyn

func DefaultDyn(t typ.Type) (string, bool)

func MustSig

func MustSig(sig string) typ.Type

func ResInfo

func ResInfo(el El) (typ.Type, lit.Lit)

func ResType

func ResType(el El) typ.Type

func Sig

func Sig(sig string) (typ.Type, error)

func Traverse

func Traverse(v Visitor, els ...El) error

Types

type Atom

type Atom struct {
	Lit lit.Lit
	lex.Src
}

Atom is a literal or type with source source offsets as returned by the parser.

func (*Atom) String

func (x *Atom) String() string

func (*Atom) Traverse

func (x *Atom) Traverse(v Visitor) error

func (*Atom) Typ

func (x *Atom) Typ() typ.Type

func (*Atom) WriteBfr

func (x *Atom) WriteBfr(b *bfr.Ctx) error

type Builtin

type Builtin []LookupFunc

Builtin is an environment based on a slice of simple resolver lookup functions.

The lookup functions are check from start to finish returning the first result. A builtin environment has no parent and cannot define resolvers.

func (Builtin) Get

func (b Builtin) Get(sym string) *Def

Get returns a resolver for the given sym

func (Builtin) Parent

func (b Builtin) Parent() Env

Parent always returns nil for the built-in lookups

func (Builtin) Supports

func (b Builtin) Supports(x byte) bool

Supports returns true for built-in schema type lookups

type Call

type Call struct {
	// Spec is the form or func specification
	Spec *Spec
	Layout
	lex.Src
}

Call is an expression with a defined specification.

func (*Call) Res

func (x *Call) Res() typ.Type

Res returns the result type or void.

func (*Call) String

func (x *Call) String() string

func (*Call) Traverse

func (x *Call) Traverse(v Visitor) error

func (*Call) Typ

func (x *Call) Typ() typ.Type

func (*Call) WriteBfr

func (x *Call) WriteBfr(b *bfr.Ctx) error

type DataScope

type DataScope struct {
	Par Env
	Def
}

DataScope is a child environment that supports relative paths and is backed by a literal

func NewDataScope

func NewDataScope(parent Env) *DataScope

NewDataScope returns a data scope with the given parent environment.

func (*DataScope) Get

func (ds *DataScope) Get(s string) *Def

Get returns a literal resolver for the relative path s or nil.

func (*DataScope) Parent

func (ds *DataScope) Parent() Env

func (*DataScope) Supports

func (ds *DataScope) Supports(x byte) bool

Supports returns true for '.', false otherwise.

type Def

type Def struct {
	// Type is the resolved definition type.
	typ.Type
	// Lit is the evaluated literal. The literal must be convertible to the definiton type.
	Lit lit.Lit
}

Def represents a definition in an environment.

func Lookup

func Lookup(env Env, sym string) *Def

Lookup returns a first resolver with symbol sym found in env or one of its ancestors. If sym starts with a known special prefix only the appropriate environments are called.

func LookupSupports

func LookupSupports(env Env, sym string, x byte) *Def

LookupSupports looks up and returns a resolver that supports behaviour indicated by x or nil.

func NewDef

func NewDef(l lit.Lit) *Def

type Dyn

type Dyn struct {
	Els []El
	lex.Src
}

Dyn is an expression with an undefined specification, that has to be determined.

func (*Dyn) String

func (x *Dyn) String() string

func (*Dyn) Traverse

func (x *Dyn) Traverse(v Visitor) error

func (*Dyn) Typ

func (x *Dyn) Typ() typ.Type

func (*Dyn) WriteBfr

func (x *Dyn) WriteBfr(b *bfr.Ctx) error

type El

type El interface {
	// WriteBfr writes the element to a bfr.Ctx.
	WriteBfr(*bfr.Ctx) error
	// String returns the xelf representation as string.
	String() string
	// Typ returns the element type.
	Typ() typ.Type
	// Source returns the source position if available.
	Source() lex.Src
	// Travers calls the appropriate visitor methods for this element and its children.
	Traverse(Visitor) error
}

El is the common interface of all language elements.

func Eval

func Eval(env Env, el El) (El, error)

func Ignore

func Ignore(src lex.Src) (El, error)

func Parse

func Parse(a *lex.Tree) (El, error)

Parse parses the syntax tree a and returns an element or an error. It needs a static environment to distinguish elements.

func Read

func Read(r io.Reader) (El, error)

Read scans and parses from r and returns an element or an error.

func Resl

func Resl(env Env, el El) (El, error)

type Env

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

	// Get looks for a definition with symbol sym defined in this environments.
	// Implementation assume sym is not empty. Callers must ensure that sym is not empty.
	Get(sym string) *Def

	// Supports returns whether the environment supports a special behaviour represented by x.
	Supports(x byte) bool
}

Env is a scoped symbol environment used to define and lookup resolvers by symbol.

func Supports

func Supports(env Env, x byte) Env

Supports returns an environment that supports behaviour indicated by x or nil.

type ExprBody

type ExprBody struct {
	Els []El
	Env Env
}

ExprBody is the body for normal functions consisting of a list of expression elements and its declaration environment that is used for execution.

func (*ExprBody) Eval

func (f *ExprBody) Eval(p *Prog, env Env, c *Call, h typ.Type) (El, error)

func (*ExprBody) Resl

func (f *ExprBody) Resl(p *Prog, env Env, c *Call, h typ.Type) (El, error)

func (*ExprBody) WriteBfr

func (f *ExprBody) WriteBfr(b *bfr.Ctx) error

type FuncScope

type FuncScope struct {
	DataScope
}

func NewFuncScope

func NewFuncScope(par Env, c *Call) *FuncScope

func (*FuncScope) Get

func (f *FuncScope) Get(s string) *Def

type Ghost

type Ghost struct{}

Ghost is a no-op visitor, that visits each element, but does not act on any.

func (Ghost) EnterCall

func (Ghost) EnterCall(*Call) error

func (Ghost) EnterDyn

func (Ghost) EnterDyn(*Dyn) error

func (Ghost) EnterNamed

func (Ghost) EnterNamed(*Tag) error

func (Ghost) LeaveCall

func (Ghost) LeaveCall(*Call) error

func (Ghost) LeaveDyn

func (Ghost) LeaveDyn(*Dyn) error

func (Ghost) LeaveNamed

func (Ghost) LeaveNamed(*Tag) error

func (Ghost) VisitLit

func (Ghost) VisitLit(*Atom) error

func (Ghost) VisitSym

func (Ghost) VisitSym(*Sym) error

func (Ghost) VisitType

func (Ghost) VisitType(*Atom) error

type Impl

type Impl interface {

	// Resl resolves a call and returns the resulting element or an error.
	//
	// A successful resolution returns a call with all related types resolved and no error.
	// If the type hint is not void, it is used to check or infer the element type.
	// When parts of the element could not be resolved it returns the special error ErrUnres.
	Resl(p *Prog, env Env, c *Call, h typ.Type) (El, error)

	// Eval evaluates a call and returns the resulting element or an error.
	//
	// A successful evaluation returns a literal and no error.
	// If the type hint is not void, it is used to check or infer the element type.
	// When parts of the element could not be evaluation it returns the special error ErrUnres,
	// and - if the context allows it - a partially resolved element.
	Eval(p *Prog, env Env, c *Call, h typ.Type) (El, error)
}

type Layout

type Layout struct {
	Sig    typ.Type
	Groups [][]El
}

Layout is a helper to validate form expression arguments.

We distinguish between tag and plain elements in the context of layouts.

The layout is formalizes by the parameter signature. It uses a number of special parameter names, that indicate to the layout how arguments must be parsed. A full form consisting of all possible kinds of accepted elements, is: <form full plain; tags; tail;>

These are the recognised parameter names:

plain accepts any number of plain elements and can be followed by tags
tags accepts any number of tag expressions and can be followed by tail
args accepts any number of leading plain elements and then tag expression
tail accepts any element and must be the last element

Explicit parameter arguments must be at the start before any special parameter.

The parameter types give hints at what types are accepted. The special parameters can only use container types. The tags parameters expect a keyer type, while all others accept an idxer type. If the type is omitted, the layout will not resolve or check that parameter.

func EvalFuncArgs

func EvalFuncArgs(p *Prog, env Env, c *Call) (*Layout, error)

func FormLayout

func FormLayout(sig typ.Type, args []El) (*Layout, error)

func FuncLayout

func FuncLayout(sig typ.Type, els []El) (*Layout, error)

FuncLayout matches arguments of x to the parameters of f and returns a layout or an error.

func ReslFuncArgs

func ReslFuncArgs(p *Prog, env Env, c *Call) (*Layout, error)

func SigLayout

func SigLayout(sig typ.Type, args []El) (*Layout, error)

func (*Layout) All

func (l *Layout) All() (res []El)

func (*Layout) Arg

func (l *Layout) Arg(idx int) El

func (*Layout) Args

func (l *Layout) Args(idx int) []El

func (*Layout) Count

func (l *Layout) Count() (n int)

func (*Layout) Eval

func (l *Layout) Eval(p *Prog, env Env, h typ.Type) error

func (*Layout) Resl

func (l *Layout) Resl(p *Prog, env Env, h typ.Type) error

func (*Layout) Tags

func (l *Layout) Tags(idx int) []*Tag

type LookupFunc

type LookupFunc = func(sym string) *Spec

LookupFunc is a simple spec lookup function used by builtins and libraries.

type ParamEnv

type ParamEnv struct {
	Par   Env
	Param lit.Lit
}

ParamEnv provides parameter resolution.

func (*ParamEnv) Get

func (ps *ParamEnv) Get(s string) *Def

func (*ParamEnv) Parent

func (ps *ParamEnv) Parent() Env

func (*ParamEnv) Supports

func (ps *ParamEnv) Supports(x byte) bool

type ParamReslEnv

type ParamReslEnv struct {
	Par Env
	Ctx *typ.Ctx
	Map map[string]typ.Type
}

func NewParamReslEnv

func NewParamReslEnv(p Env, c *typ.Ctx) *ParamReslEnv

func (*ParamReslEnv) Get

func (ps *ParamReslEnv) Get(s string) *Def

func (*ParamReslEnv) Parent

func (ps *ParamReslEnv) Parent() Env

func (*ParamReslEnv) Supports

func (ps *ParamReslEnv) Supports(x byte) bool

type Prog

type Prog struct {
	// Ctx is the type context that stores type variable bindings.
	*typ.Ctx
	// Unres is a list of all unresolved expressions and type and symbol references.
	Unres []El

	Dyn func(fst typ.Type) (sym string, consume bool)
}

Prog is the resolution type context and also collects unresolved elements.

func NewProg

func NewProg() *Prog

func (*Prog) BuiltinCall

func (p *Prog) BuiltinCall(env Env, name string, args []El, src lex.Src) (*Call, error)

BuiltinCall looks up the builtin spec by name and returns a new call or returns an error.

func (*Prog) Eval

func (p *Prog) Eval(env Env, el El, h typ.Type) (_ El, err error)

func (*Prog) EvalAll

func (p *Prog) EvalAll(env Env, els []El, hint typ.Type) (res []El, err error)

func (*Prog) NewCall

func (p *Prog) NewCall(s *Spec, args []El, src lex.Src) (*Call, error)

NewCall returns a new call or an error if arguments do not match the spec signature. The call signature is instantiated in the programs type context.

func (*Prog) Realize

func (p *Prog) Realize(el El) error

Realize finalizes all types in el or returns an error. If successful, el is independent of its type context.

func (*Prog) Resl

func (p *Prog) Resl(env Env, el El, h typ.Type) (_ El, err error)

Resolve resolves x within env and returns the result or an error.

This method will not resolve any element itself but instead tries to look up an applicable resolver in the environment. If it cannot find a resolver it will add the element to the context's unresolved slice. The resolver implementations usually use this method either directly or indirectly to resolve arguments, which are then again added to the unresolved elements when appropriate.

func (*Prog) ReslAll

func (p *Prog) ReslAll(env Env, els []El, h typ.Type) (res []El, err error)

ReslAll resolves all element or returns the first error.

type ProgEnv

type ProgEnv struct {
	Par    Env
	Result *lit.Dict
}

ProgEnv provides global result resolution.

func (*ProgEnv) Get

func (ps *ProgEnv) Get(s string) *Def

func (*ProgEnv) Parent

func (ps *ProgEnv) Parent() Env

func (*ProgEnv) Supports

func (ps *ProgEnv) Supports(x byte) bool

type Scope

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

Scope is a child environment based on a map of resolvers.

func NewScope

func NewScope(parent Env) *Scope

NewScope returns a child scope with the given parent environment.

func (*Scope) Def

func (s *Scope) Def(sym string, d *Def) error

Def defines a symbol resolver binding for s and d or returns an error.

func (*Scope) Get

func (s *Scope) Get(sym string) *Def

Get returns a resolver with symbol s defined in this scope or nil.

func (*Scope) Parent

func (s *Scope) Parent() Env

func (*Scope) Supports

func (s *Scope) Supports(byte) bool

Supports returns always false for simple scopes.

type Spec

type Spec struct {
	typ.Type
	Impl
}

func (*Spec) Arg

func (sp *Spec) Arg() []typ.Param

Arg returns the argument parameters or nil.

func (*Spec) IsZero

func (sp *Spec) IsZero() bool

func (*Spec) Res

func (sp *Spec) Res() typ.Type

Res returns the result type or void.

func (*Spec) String

func (sp *Spec) String() string

func (*Spec) Typ

func (sp *Spec) Typ() typ.Type

func (*Spec) WriteBfr

func (sp *Spec) WriteBfr(b *bfr.Ctx) error

type Sym

type Sym struct {
	Name string
	// Type is the resolved type of lit in this context or void.
	Type typ.Type
	// Lit is the resolved literal or nil. Conversion may be required.
	Lit lit.Lit
	lex.Src
}

Sym is an identifier, that refers to a definition.

func (*Sym) Key

func (x *Sym) Key() string

func (*Sym) String

func (x *Sym) String() string

func (*Sym) Traverse

func (x *Sym) Traverse(v Visitor) error

func (*Sym) Typ

func (x *Sym) Typ() typ.Type

func (*Sym) WriteBfr

func (x *Sym) WriteBfr(b *bfr.Ctx) error

type Tag

type Tag struct {
	Name string
	El   El
	lex.Src
}

Tag is a named elements. Its meaning is determined by the parent's specification.

func NewNamed

func NewNamed(name string, els ...El) *Tag

func (*Tag) Arg

func (x *Tag) Arg() El

func (*Tag) Args

func (x *Tag) Args() []El

func (*Tag) Dyn

func (x *Tag) Dyn() *Dyn

func (*Tag) Key

func (x *Tag) Key() string

func (*Tag) String

func (x *Tag) String() string

func (*Tag) Traverse

func (x *Tag) Traverse(v Visitor) error

func (*Tag) Typ

func (x *Tag) Typ() typ.Type

func (*Tag) WriteBfr

func (x *Tag) WriteBfr(b *bfr.Ctx) error

type Visitor

type Visitor interface {
	VisitLit(*Atom) error
	VisitType(*Atom) error
	VisitSym(*Sym) error
	EnterNamed(*Tag) error
	LeaveNamed(*Tag) error
	EnterDyn(*Dyn) error
	LeaveDyn(*Dyn) error
	EnterCall(*Call) error
	LeaveCall(*Call) error
}

Jump to

Keyboard shortcuts

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