go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

loop.go (1543B)


      1 package engine
      2 
      3 import (
      4 	"bufio"
      5 	"context"
      6 	"fmt"
      7 	"io"
      8 	"strings"
      9 )
     10 
     11 // Loop starts an engine execution loop with the given symbol as the starting node.
     12 //
     13 // The root reads inputs from the provided reader, one line at a time.
     14 //
     15 // It will execute until running out of bytecode in the buffer.
     16 //
     17 // Any error not handled by the engine will terminate the oop and return an error.
     18 //
     19 // Rendered output is written to the provided writer.
     20 //
     21 // If initial is set, the value will be used for the first (initializing) execution
     22 // If nil, an empty byte value will be used.
     23 func Loop(ctx context.Context, en Engine, reader io.Reader, writer io.Writer, initial []byte) error {
     24 	defer en.Finish()
     25 	if initial == nil {
     26 		initial = []byte{}
     27 	}
     28 	cont, err := en.Exec(ctx, initial)
     29 	if err != nil {
     30 		return err
     31 	}
     32 	l, err := en.Flush(ctx, writer)
     33 	if err != nil {
     34 		if err != ErrFlushNoExec {
     35 			return err
     36 		}
     37 	}
     38 	if l > 0 {
     39 		writer.Write([]byte{0x0a})
     40 	}
     41 	if !cont {
     42 		return nil
     43 	}
     44 
     45 	running := true
     46 	bufReader := bufio.NewReader(reader)
     47 	for running {
     48 		in, err := bufReader.ReadString('\n')
     49 		if err == io.EOF {
     50 			logg.DebugCtxf(ctx, "EOF found, that's all folks")
     51 			return nil
     52 		}
     53 		if err != nil {
     54 			return fmt.Errorf("cannot read input: %v\n", err)
     55 		}
     56 		in = strings.TrimSpace(in)
     57 		running, err = en.Exec(ctx, []byte(in))
     58 		if err != nil {
     59 			return fmt.Errorf("unexpected termination: %v\n", err)
     60 		}
     61 		l, err := en.Flush(ctx, writer)
     62 		if err != nil {
     63 			return err
     64 		}
     65 		if l > 0 {
     66 			writer.Write([]byte{0x0a})
     67 		}
     68 	}
     69 	return nil
     70 }