Add Golang runner to runtime

Signed-off-by: AKP <tom@tdpain.net>
This commit is contained in:
akp 2021-10-21 09:44:34 +01:00
parent 285adaa58b
commit 0c40717eab
No known key found for this signature in database
GPG key ID: AA5726202C8879B7
4 changed files with 181 additions and 3 deletions

View file

@ -4,14 +4,14 @@ import "errors"
type BaseChallenge struct{}
func (b *BaseChallenge) one(instr string) (interface{}, error) {
func (b *BaseChallenge) One(instr string) (interface{}, error) {
return nil, errors.New("not implemented")
}
func (b *BaseChallenge) two(instr string) (interface{}, error) {
func (b *BaseChallenge) Two(instr string) (interface{}, error) {
return nil, errors.New("not implemented")
}
func (b *BaseChallenge) vis(instr string, outdir string) error {
func (b *BaseChallenge) Vis(instr string, outdir string) error {
return errors.New("not implemented")
}

View file

@ -0,0 +1,95 @@
package runners
import (
"bytes"
_ "embed"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"text/template"
)
const golangInstallation = "go"
type golangRunner struct {
dir string
tasks []*Task
}
func newGolangRunner(dir string) Runner {
return &golangRunner{
dir: dir,
}
}
func (g *golangRunner) Queue(task *Task) {
}
//go:embed interface/go.go
var golangInterface []byte
func (g *golangRunner) Run() chan ResultOrError {
wrapperFilename := "runtime-wrapper.go"
wrapperExecutable := "runtime-wrapper"
wrapperFilepath := filepath.Join(g.dir, wrapperFilename)
wrapperExecutableFilepath := filepath.Join(g.dir, wrapperExecutable)
// generate interaction data
taskJSON, err := json.Marshal(g.tasks)
if err != nil {
return makeErrorChan(err)
}
// determine package import path
buildPath := fmt.Sprintf("github.com/codemicro/adventOfCode/challenges/%s", filepath.Base(g.dir))
importPath := buildPath + "/go"
// generate code
var wrapperContent []byte
{
tpl := template.Must(template.New("").Parse(string(golangInterface)))
b := bytes.NewBuffer(wrapperContent)
err := tpl.Execute(b, struct {
ImportPath string
}{importPath})
if err != nil {
return makeErrorChan(err)
}
}
// save interaction code
err = ioutil.WriteFile(wrapperFilepath, wrapperContent, 0644)
if err != nil {
return makeErrorChan(err)
}
// compile executable
cmd := exec.Command(golangInstallation, "build", "-O", wrapperExecutableFilepath, buildPath)
err = cmd.Run()
if err != nil {
return makeErrorChan(err)
}
if !cmd.ProcessState.Success() {
return makeErrorChan(errors.New("compilation failed, hence cannot continue"))
}
// run executable
cmd = exec.Command(wrapperExecutableFilepath)
cmd.Dir = g.dir
cmd.Stdin = bytes.NewReader(append(taskJSON, '\n'))
return readResultsFromCommand(cmd, func() {
// remove leftover files
_ = os.Remove(wrapperFilepath)
_ = os.Remove(wrapperExecutableFilepath)
})
}

View file

@ -0,0 +1,81 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"github.com/codemicro/adventOfCode/runtime/runners"
"os"
"time"
chcode "{{ .ImportPath }}"
)
func sendResult(taskID string, ok bool, output string, duration float32) {
x := runners.Result{
TaskID: taskID,
Ok: ok,
Output: output,
Duration: duration,
}
dat, err := json.Marshal(&x)
if err != nil {
panic(err)
}
fmt.Println(string(dat))
}
func run() error {
scanner := bufio.NewScanner(os.Stdin)
var tasksBytes []byte
if scanner.Scan() {
tasksBytes = scanner.Bytes()
} else if err := scanner.Err(); err != nil {
return err
}
var tasks []*runners.Task
if err := json.Unmarshal(tasksBytes, &tasks); err != nil {
return err
}
for _, task := range tasks {
var run func() (interface{}, error)
switch task.Part {
case runners.PartOne:
run = func() (interface{}, error) {
return chcode.Challenge{}.One(task.Input)
}
case runners.PartTwo:
run = func() (interface{}, error) {
return chcode.Challenge{}.Two(task.Input)
}
case runners.Visualise:
run = func() (interface{}, error) {
return chcode.Challenge{}.Vis(task.Input, task.OutputDir)
}
}
startTime := time.Now()
res, err := run()
endTIme := time.Now()
runningTime := float32(endTIme.Sub(startTime).Seconds())
if err != nil {
sendResult(task.TaskID, false, err.Error(), runningTime)
} else {
sendResult(task.TaskID, true, fmt.Sprintf("%v", res), runningTime)
}
}
return nil
}
func main() {
if err := run(); err != nil {
panic(err)
}
}

View file

@ -22,8 +22,10 @@ type RunnerCreator func(dir string) Runner
var Available = map[string]RunnerCreator{
"py": newPythonRunner,
"go": newGolangRunner,
}
var RunnerNames = map[string]string{
"py": "Python",
"go": "Golang",
}