Update Nim runner

This commit is contained in:
akp 2021-12-11 00:23:54 +00:00
parent 6502ef4ff4
commit 34582c5c75
No known key found for this signature in database
GPG key ID: AA5726202C8879B7
4 changed files with 129 additions and 92 deletions

View file

@ -22,10 +22,12 @@ type
input: string
output_dir: Option[string]
let tasksString = readLine(stdin)
let tasks = to(parseJson(tasksString), seq[Task])
while true:
let
taskString = readLine(stdin)
task = to(parseJson(taskString), Task)
for _, task in tasks:
var runProc: proc(): string
case task.part

View file

@ -0,0 +1,122 @@
package runners
import (
"bytes"
_ "embed"
"encoding/json"
"errors"
"fmt"
au "github.com/logrusorgru/aurora"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)
const (
nimInstallation = "nim"
nimWrapperFilename = "runtimeWrapper.nim"
nimWrapperExecutableFilename = "runtimeWrapper"
)
type nimRunner struct {
dir string
cmd *exec.Cmd
wrapperFilepath string
executableFilepath string
stdin io.WriteCloser
}
func newNimRunner(dir string) Runner {
return &nimRunner{
dir: dir,
}
}
//go:embed interface/nim.nim
var nimInterface []byte
func (n *nimRunner) Start() error {
n.wrapperFilepath = filepath.Join(n.dir, nimWrapperFilename)
n.executableFilepath = filepath.Join(n.dir, nimWrapperExecutableFilename)
// save interaction code
err := ioutil.WriteFile(n.wrapperFilepath, nimInterface, 0644)
if err != nil {
return err
}
// compile
stderrBuffer := new(bytes.Buffer)
cmd := exec.Command(nimInstallation, "compile", "-o:"+n.executableFilepath, "-d:release", n.wrapperFilepath)
cmd.Stderr = stderrBuffer
err = cmd.Run()
if err != nil {
return fmt.Errorf("compilation failed: %s: %s", err, stderrBuffer.String())
}
if !cmd.ProcessState.Success() {
return errors.New("compilation failed, hence cannot continue")
}
// now we run!
absExecPath, err := filepath.Abs(n.executableFilepath)
if err != nil {
return err
}
n.cmd = exec.Command(absExecPath)
n.cmd.Dir = n.dir
if stdin, err := setupBuffers(n.cmd); err != nil {
return err
} else {
n.stdin = stdin
}
return n.cmd.Start()
}
func (n *nimRunner) Stop() error {
if n.cmd == nil || n.cmd.Process == nil {
return nil
}
return n.cmd.Process.Kill()
}
func (n *nimRunner) Cleanup() error {
if n.wrapperFilepath != "" {
_ = os.Remove(n.wrapperFilepath)
}
if n.executableFilepath != "" {
_ = os.Remove(n.executableFilepath)
}
return nil
}
func (n *nimRunner) Run(task *Task) (*Result, error) {
taskJSON, err := json.Marshal(task)
if err != nil {
return nil, err
}
_, _ = n.stdin.Write(append(taskJSON, '\n'))
res := new(Result)
for {
inp, err := checkWait(n.cmd)
if err != nil {
return nil, err
}
err = json.Unmarshal(inp, res)
if err != nil {
// echo anything that won't parse to stdout (this lets us add debug print statements)
fmt.Printf("[%s] %v\n", au.BrightRed("DBG"), strings.TrimSpace(string(inp)))
} else {
break
}
}
return res, nil
}

View file

@ -1,87 +0,0 @@
package runners
import (
"bytes"
_ "embed"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
)
const nimInstallation = "nim"
type nimRunner struct {
dir string
tasks []*Task
}
func newNimRunner(dir string) Runner {
return &nimRunner{
dir: dir,
}
}
func (n *nimRunner) Queue(task *Task) {
n.tasks = append(n.tasks, task)
}
//go:embed interface/nim.nim
var nimInterface []byte
func (n *nimRunner) Run() (chan ResultOrError, func()) {
wrapperExecutable := "runtimeWrapper"
wrapperFilename := wrapperExecutable + ".nim"
executableFilepath := filepath.Join(n.dir, wrapperExecutable)
wrapperFilepath := filepath.Join(n.dir, wrapperFilename)
// generate interaction data
taskJSON, err := json.Marshal(n.tasks)
if err != nil {
return makeErrorChan(err), nil
}
// save interaction code
err = ioutil.WriteFile(wrapperFilepath, nimInterface, 0644)
if err != nil {
return makeErrorChan(err), nil
}
fmt.Print("Compiling...\r")
defer fmt.Print("\n\n")
// compile
stderrBuffer := new(bytes.Buffer)
cmd := exec.Command(nimInstallation, "compile", "-o:"+executableFilepath, "-d:release", wrapperFilepath)
cmd.Stderr = stderrBuffer
err = cmd.Run()
if err != nil {
return makeErrorChan(fmt.Errorf("compilation failed: %s: %s", err, stderrBuffer.String())), nil
}
if !cmd.ProcessState.Success() {
return makeErrorChan(errors.New("compilation failed, hence cannot continue")), nil
}
fmt.Print("Running... ")
absExecPath, err := filepath.Abs(executableFilepath)
if err != nil {
return makeErrorChan(err), nil
}
// run
cmd = exec.Command(absExecPath)
cmd.Dir = n.dir
cmd.Stdin = bytes.NewReader(append(taskJSON, '\n'))
return readResultsFromCommand(cmd), func() {
_ = os.Remove(executableFilepath)
_ = os.Remove(wrapperFilepath)
}
}

View file

@ -25,11 +25,11 @@ type RunnerCreator func(dir string) Runner
var Available = map[string]RunnerCreator{
"py": newPythonRunner,
"go": newGolangRunner,
//"nim": newNimRunner,
"nim": newNimRunner,
}
var RunnerNames = map[string]string{
"py": "Python",
"go": "Golang",
//"nim": "Nim",
"nim": "Nim",
}