Runtime: add Nim runner
Hooray!
This commit is contained in:
parent
629fff4414
commit
cb36157b56
3 changed files with 140 additions and 0 deletions
56
runtime/runners/interface/nim.nim
Normal file
56
runtime/runners/interface/nim.nim
Normal file
|
@ -0,0 +1,56 @@
|
|||
import std/strutils
|
||||
import std/options
|
||||
import std/json
|
||||
import std/monotimes
|
||||
import std/times
|
||||
|
||||
from nim/challenge as solutions import nil
|
||||
|
||||
proc sendResult(taskID: string, ok: bool, output: string, duration: float64) =
|
||||
let jobj = %* {
|
||||
"task_id": taskID,
|
||||
"ok": ok,
|
||||
"output": output,
|
||||
"duration": duration,
|
||||
}
|
||||
echo $jobj
|
||||
|
||||
type
|
||||
Task = ref object
|
||||
task_id: string
|
||||
part: int
|
||||
input: string
|
||||
output_dir: Option[string]
|
||||
|
||||
let tasksString = readLine(stdin)
|
||||
let tasks = to(parseJson(tasksString), seq[Task])
|
||||
|
||||
for _, task in tasks:
|
||||
var runProc: proc(): string
|
||||
|
||||
case task.part
|
||||
of 1:
|
||||
runProc = proc(): string = $(solutions.partOne(task.input))
|
||||
of 2:
|
||||
runProc = proc(): string = $(solutions.partTwo(task.input))
|
||||
else:
|
||||
sendResult(task.task_id, false, "unknown task part", 0.0)
|
||||
|
||||
var
|
||||
result: string
|
||||
error: string
|
||||
|
||||
let startTime = getMonoTime()
|
||||
try:
|
||||
result = runProc()
|
||||
except:
|
||||
error = getCurrentExceptionMsg()
|
||||
let endTime = getMonoTime()
|
||||
|
||||
let runningTime = endTime - startTime
|
||||
let runningTimeSeconds = float(inNanoseconds(runningTime)) / float(1000000000)
|
||||
|
||||
if error != "":
|
||||
sendResult(task.task_id, false, error, runningTimeSeconds)
|
||||
else:
|
||||
sendResult(task.task_id, true, result, runningTimeSeconds)
|
82
runtime/runners/nimRunner.go
Normal file
82
runtime/runners/nimRunner.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -23,9 +23,11 @@ type RunnerCreator func(dir string) Runner
|
|||
var Available = map[string]RunnerCreator{
|
||||
"py": newPythonRunner,
|
||||
"go": newGolangRunner,
|
||||
"nim": newNimRunner,
|
||||
}
|
||||
|
||||
var RunnerNames = map[string]string{
|
||||
"py": "Python",
|
||||
"go": "Golang",
|
||||
"nim": "Nim",
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue