evaluator

package
v0.1.65 Latest Latest
Warning

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

Go to latest
Published: Mar 21, 2024 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package evaluator executes a given Evy program by walking its AST.

Initially, an Evy program is turned into a sequence of tokens by the lexer. Then, the parser generates an Abstract Syntax Tree(AST) from the tokens. Finally, the Evaluator of this package walks the AST and executes the program.

The Evaluator is a tree-walking interpreter. It directly interprets the AST, without any preprocessing, intermediate representation, or compilation step. This is a straightforward way to implement an interpreter, but it trades off execution performance for simplicity.

The Evaluator uses different Runtime implementations to target different environments. For example, there is a JS/WASM runtime for the browser, which has full support for all graphics built-in functions. There is also a command line environment, which does not have graphics functions support.

The NewEvaluator function creates a new Evaluator for a given Runtime. The evaluator can then be used by either:

After the Evaluator has finished evaluating all top-level code and returned, the environment is responsible for starting an event loop if external events such as key press events or pointer/mouse move events are supported.

In the event loop, new events are queued and handled sequentially by calling the Evaluator.HandleEvent function. Each event is passed to its event handler once. The event handler body runs to completion, and then the control is returned to the event loop. The event loop is terminated when the Evaluator is stopped. For a sample implementation of an event loop, see the main package in the pkg/wasm directory used in the browser environment.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrStopped = errors.New("stopped")

	ErrPanic         = errors.New("panic")
	ErrBounds        = fmt.Errorf("%w: index out of bounds", ErrPanic)
	ErrRangevalue    = fmt.Errorf("%w: bad range value", ErrPanic)
	ErrMapKey        = fmt.Errorf("%w: no value for map key", ErrPanic)
	ErrSlice         = fmt.Errorf("%w: bad slice", ErrPanic)
	ErrBadArguments  = fmt.Errorf("%w: bad arguments", ErrPanic)
	ErrAnyConversion = fmt.Errorf("%w: error converting any to type", ErrPanic)
	ErrVarNotSet     = fmt.Errorf("%w: variable has not been set yet", ErrPanic)

	ErrInternal         = errors.New("internal error")
	ErrUnknownNode      = fmt.Errorf("%w: unknown AST node", ErrInternal)
	ErrType             = fmt.Errorf("%w: type error", ErrInternal)
	ErrRangeType        = fmt.Errorf("%w: bad range type", ErrInternal)
	ErrOperation        = fmt.Errorf("%w: unknown operation", ErrInternal)
	ErrAssignmentTarget = fmt.Errorf("%w: bad assignment target", ErrInternal)
)

The Evaluator can return the following sentinel errors:

  • ErrStopped is returned when the program has been stopped externally.
  • ErrPanic and errors wrapping ErrPanic report runtime errors, such as an index out of bounds error.
  • ErrInternal and errors wrapping ErrInternal report internal errors of the evaluator or AST. These errors should not occur.

Functions

func BuiltinDecls

func BuiltinDecls() parser.Builtins

BuiltinDecls returns the signatures of all built-in functions and event handlers, as well as predefined global variables, for use by the parser.Parse function.

Types

type Error

type Error struct {
	Token *lexer.Token
	// contains filtered or unexported fields
}

Error is an Evy evaluator error associated with a lexer.Token that points to a location in the Evy source code that caused the error.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface and returns the wrapped error message prefixed with the source location.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the wrapped error.

type Evaluator

type Evaluator struct {
	// Stopped flags the evaluation to be stopped.
	// The unsynchronized access to the Stopped field is safe in WASM because
	// WASM is a single-threaded environment. TinyGo does not currently support
	// synchronization in reactor mode, see
	// https://github.com/tinygo-org/tinygo/issues/2735.
	Stopped           bool
	EventHandlerNames []string
	// contains filtered or unexported fields
}

Evaluator is a tree-walking interpreter that directly interprets the AST using the Run and Eval methods. The HandleEvent method can be used to allow the evaluator to handle events. The Evaluator does not preprocess or compile the AST to an intermediate representation, which results in a straightforward implementation that trades off execution performance for simplicity.

func NewEvaluator

func NewEvaluator(rt Runtime) *Evaluator

NewEvaluator creates a new Evaluator for a given Runtime. Runtimes target different environments, such as the browser or the command line.

func (*Evaluator) Eval

func (e *Evaluator) Eval(prog *parser.Program) error

Eval evaluates a parser.Program, which is the root node of the AST. The program's statements are evaluated in order. If a runtime panic occurs, a wrapped ErrPanic is returned. If an internal error occurs, a wrapped ErrInternal is returned. Evaluation is also stopped if the built-in exit function is called, which results in an ExitError. If the evaluator's Stopped flag is externally set to true, evaluation is stopped and ErrStopped is returned.

func (*Evaluator) HandleEvent

func (e *Evaluator) HandleEvent(ev Event) error

HandleEvent is called by an environment's event loop, passing the event ev to be handled. If the event's name and parameters match those of a predefined, built-in event handler signature, and if there is an event handler implementation in the Evy source code with the following signature:

on <event-name> [<event-params>]

then the event handler implementation of the Evy source code is executed.

For more details, see the built-in documentation on event handlers.

func (*Evaluator) Run

func (e *Evaluator) Run(input string) error

Run is a convenience function that parses and evaluates a given Evy source code input string. See the Evaluator type and Evaluator.Eval method for details on evaluation and errors.

type Event

type Event struct {
	Name   string
	Params []any
}

Event is a generic data structure that is passed to the Evaluator through the Evaluator.HandleEvent function. The evaluator tries to match the event's name and parameters to an event handler implementation in the Evy source code. If a matching handler is found, it is executed.

type ExitError

type ExitError int

ExitError is returned by Evaluator.Eval if Evy's builtin exit function is called.

func (ExitError) Error

func (e ExitError) Error() string

Error implements the error interface and returns message containing the exit status.

type GraphicsRuntime

type GraphicsRuntime interface {
	Move(x, y float64)
	Line(x, y float64)
	Rect(dx, dy float64)
	Circle(radius float64)
	Width(w float64)
	Color(s string)
	Clear(color string)

	// advanced graphics functions
	Poly(vertices [][]float64)
	Ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle float64)
	Stroke(s string)
	Fill(s string)
	Dash(segments []float64)
	Linecap(s string)
	Text(s string)
	// font optionally sets font properties such as family, size or weight.
	// font properties match their CSS properties. Here's an exhaustive list
	// of mapped properties:
	//
	//		font {
	//			family: "Georgia, serif"
	//			size: 3 // relative to canvas, numbers only no "12px" etc.
	//			weight: 100 | 200| 300 | 400 == "normal" | 500 | 600 | 700 == "bold" | 800 | 900
	//			style: "italic" | "oblique 35deg" | "normal"
	//			baseline: "top" | "middle" | "bottom"
	//			align: "left" | "center" | "right"
	//			letterspacing: 1 // number, see size. extra inter-character space. negative allowed.
	//		}
	Font(props map[string]any)
	Gridn(unit float64, color string)
}

The GraphicsRuntime interface contains all methods that are required by the graphics built-ins. For more details see the graphics built-ins documentation.

type PanicError

type PanicError string

PanicError is returned by Evaluator.Eval if Evy's builtin panic function is called or a runtime error occurs.

func (PanicError) Error

func (e PanicError) Error() string

Error implements the error interface and returns the panic message.

func (*PanicError) Unwrap

func (e *PanicError) Unwrap() error

Unwrap returns the ErrPanic sentinel error so that it can be used in

errors.Is(err, evaluator.ErrPanic)

type Runtime

type Runtime interface {
	GraphicsRuntime
	Print(string)
	Read() string
	Cls()
	Sleep(dur time.Duration)
	Yielder() Yielder
}

The Runtime interface must be implemented by an environment in order to execute Evy source code and Evy builtins. To create a new runtime implementation, you can embed UnimplementedRuntime and override the methods that your runtime can provide. For example, there is a jsRuntime implementation for the browser, which has full support for all graphics built-in functions. There is also a command-line environment implementation, which does not have graphics function support. For more details on the built-in functions, see the built-ins documentation.

type UnimplementedRuntime

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

UnimplementedRuntime implements Runtime with no-ops and prints a "<func> not implemented" message.

func (*UnimplementedRuntime) Circle

func (rt *UnimplementedRuntime) Circle(float64)

Circle is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Clear

func (rt *UnimplementedRuntime) Clear(string)

Clear is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Cls

func (rt *UnimplementedRuntime) Cls()

Cls is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Color

func (rt *UnimplementedRuntime) Color(string)

Color is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Dash

func (rt *UnimplementedRuntime) Dash([]float64)

Dash is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Ellipse

Ellipse is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Fill

func (rt *UnimplementedRuntime) Fill(string)

Fill is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Font

func (rt *UnimplementedRuntime) Font(map[string]any)

Font is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Gridn

func (rt *UnimplementedRuntime) Gridn(float64, string)

Gridn is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Line

Line is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Linecap

func (rt *UnimplementedRuntime) Linecap(string)

Linecap is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Move

Move is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Poly

func (rt *UnimplementedRuntime) Poly([][]float64)

Poly is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Print

func (rt *UnimplementedRuntime) Print(s string)

Print prints to os.Stdout.

func (*UnimplementedRuntime) Read

func (rt *UnimplementedRuntime) Read() string

Read is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Rect

Rect is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Sleep

func (rt *UnimplementedRuntime) Sleep(time.Duration)

Sleep is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Stroke

func (rt *UnimplementedRuntime) Stroke(string)

Stroke is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Text

func (rt *UnimplementedRuntime) Text(string)

Text is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Width

func (rt *UnimplementedRuntime) Width(float64)

Width is a no-op that prints an "unimplemented" message.

func (*UnimplementedRuntime) Yielder

func (rt *UnimplementedRuntime) Yielder() Yielder

Yielder is a no-op that prints an "unimplemented" message.

type Yielder

type Yielder interface {
	Yield()
}

Yielder is a runtime-implemented mechanism that causes the evaluation process to periodically give up control to the runtime. The Yield method of the Yielder interface is called at the beginning of each evaluation step. This allows the runtime to handle external tasks, such as processing events. For a sample implementation, see the sleepingYielder of the browser environment in the pkg/wasm directory.

Jump to

Keyboard shortcuts

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