2023-04-09 16:58:35 +02:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-04-10 08:54:52 +02:00
|
|
|
"io"
|
2023-04-10 09:07:08 +02:00
|
|
|
"log"
|
2023-04-09 16:58:35 +02:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-04-12 19:04:36 +02:00
|
|
|
// Loop starts an engine execution loop with the given symbol as the starting node.
|
|
|
|
//
|
|
|
|
// The root reads inputs from the provided reader, one line at a time.
|
|
|
|
//
|
|
|
|
// It will execute until running out of bytecode in the buffer.
|
|
|
|
//
|
|
|
|
// Any error not handled by the engine will terminate the oop and return an error.
|
|
|
|
//
|
|
|
|
// Rendered output is written to the provided writer.
|
2023-04-13 01:38:33 +02:00
|
|
|
func Loop(en *Engine, reader io.Reader, writer io.Writer, ctx context.Context) error {
|
|
|
|
err := en.WriteResult(writer, ctx)
|
2023-04-12 19:04:36 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-04-12 15:20:09 +02:00
|
|
|
writer.Write([]byte{0x0a})
|
2023-04-09 16:58:35 +02:00
|
|
|
|
|
|
|
running := true
|
2023-04-10 08:54:52 +02:00
|
|
|
bufReader := bufio.NewReader(reader)
|
2023-04-09 16:58:35 +02:00
|
|
|
for running {
|
2023-04-10 08:54:52 +02:00
|
|
|
in, err := bufReader.ReadString('\n')
|
2023-04-10 09:07:08 +02:00
|
|
|
if err == io.EOF {
|
|
|
|
log.Printf("EOF found, that's all folks")
|
|
|
|
return nil
|
|
|
|
}
|
2023-04-09 16:58:35 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot read input: %v\n", err)
|
|
|
|
}
|
|
|
|
in = strings.TrimSpace(in)
|
|
|
|
running, err = en.Exec([]byte(in), ctx)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unexpected termination: %v\n", err)
|
|
|
|
}
|
2023-04-12 09:30:35 +02:00
|
|
|
err = en.WriteResult(writer, ctx)
|
2023-04-10 16:26:18 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-04-10 08:54:52 +02:00
|
|
|
writer.Write([]byte{0x0a})
|
2023-04-12 15:20:09 +02:00
|
|
|
|
2023-04-09 16:58:35 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|