Add Golang runner to runtime
Signed-off-by: AKP <tom@tdpain.net>
This commit is contained in:
parent
285adaa58b
commit
0c40717eab
4 changed files with 181 additions and 3 deletions
|
@ -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")
|
||||
}
|
||||
|
|
95
runtime/runners/golangRunner.go
Normal file
95
runtime/runners/golangRunner.go
Normal 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)
|
||||
})
|
||||
}
|
81
runtime/runners/interface/go.go
Normal file
81
runtime/runners/interface/go.go
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue