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:
- Passing an Evy program directly to the Evaluator.Run function.
- Passing the pre-generated AST to the Evaluator.Eval function.
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 ¶
- Variables
- func BuiltinDecls() parser.Builtins
- type Error
- type Evaluator
- type Event
- type ExitError
- type GraphicsRuntime
- type PanicError
- type Runtime
- type UnimplementedRuntime
- func (rt *UnimplementedRuntime) Circle(float64)
- func (rt *UnimplementedRuntime) Clear(string)
- func (rt *UnimplementedRuntime) Cls()
- func (rt *UnimplementedRuntime) Color(string)
- func (rt *UnimplementedRuntime) Dash([]float64)
- func (rt *UnimplementedRuntime) Ellipse(float64, float64, float64, float64, float64, float64, float64)
- func (rt *UnimplementedRuntime) Fill(string)
- func (rt *UnimplementedRuntime) Font(map[string]any)
- func (rt *UnimplementedRuntime) Gridn(float64, string)
- func (rt *UnimplementedRuntime) Line(float64, float64)
- func (rt *UnimplementedRuntime) Linecap(string)
- func (rt *UnimplementedRuntime) Move(float64, float64)
- func (rt *UnimplementedRuntime) Poly([][]float64)
- func (rt *UnimplementedRuntime) Print(s string)
- func (rt *UnimplementedRuntime) Read() string
- func (rt *UnimplementedRuntime) Rect(float64, float64)
- func (rt *UnimplementedRuntime) Sleep(time.Duration)
- func (rt *UnimplementedRuntime) Stroke(string)
- func (rt *UnimplementedRuntime) Text(string)
- func (rt *UnimplementedRuntime) Width(float64)
- func (rt *UnimplementedRuntime) Yielder() Yielder
- type Yielder
Constants ¶
This section is empty.
Variables ¶
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 ¶
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 ¶
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.
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 ¶
NewEvaluator creates a new Evaluator for a given Runtime. Runtimes target different environments, such as the browser or the command line.
func (*Evaluator) Eval ¶
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 ¶
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.
type Event ¶
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.
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 ¶
func (rt *UnimplementedRuntime) Ellipse(float64, float64, float64, float64, float64, float64, float64)
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 ¶
func (rt *UnimplementedRuntime) Line(float64, float64)
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 ¶
func (rt *UnimplementedRuntime) Move(float64, float64)
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 ¶
func (rt *UnimplementedRuntime) Rect(float64, float64)
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.