Преглед на файлове

support multiple languages

python initially, because @KLINGTdotNET.
Lucas Stadler преди 11 години
родител
ревизия
962bab9c58
променени са 1 файла, в които са добавени 50 реда и са изтрити 22 реда
  1. 50 22
      go/linguaevalia/linguaevalia.go

+ 50 - 22
go/linguaevalia/linguaevalia.go

15
)
15
)
16
16
17
type Language interface {
17
type Language interface {
18
	Eval(code string) (result []byte, err error)
18
	RunFile(f *os.File) (result []byte, err error)
19
	Extension() string
19
}
20
}
20
21
21
type LanguageGo struct{}
22
type LanguageGo struct{}
23
type LanguagePython struct{}
22
24
23
var Go = LanguageGo{}
25
var Go = LanguageGo{}
26
var Python = LanguagePython{}
24
27
25
func (g LanguageGo) Eval(code string) ([]byte, error) {
26
	// write code to temp file
27
	f, err := writeCode(code)
28
	defer f.Close()
29
	if err != nil {
30
		return nil, err
31
	}
32
	// `go run` it
33
	res, err := runCode(f)
34
	if err != nil {
35
		return res, err
36
	}
37
	// remove the file
38
	os.Remove(f.Name())
39
	// return output
40
	return res, nil
28
var languageMappings = map[string]Language{
29
	"go":     Go,
30
	"python": Python,
41
}
31
}
42
32
43
func writeCode(code string) (*os.File, error) {
33
func writeCode(code string, extension string) (*os.File, error) {
44
	// create tmp file
34
	// create tmp file
45
	f, err := os.Create("/tmp/linguaevalia-go.go") // FIXME: actually create a tmpfile
35
	f, err := os.Create(fmt.Sprintf("/tmp/linguaevalia-%s.%s", extension, extension)) // FIXME: actually create a tmpfile
46
	if err != nil {
36
	if err != nil {
47
		return f, err
37
		return f, err
48
	}
38
	}
54
	return f, nil
44
	return f, nil
55
}
45
}
56
46
57
func runCode(f *os.File) ([]byte, error) {
47
func (l LanguageGo) RunFile(f *os.File) ([]byte, error) {
58
	cmd := exec.Command("go", "run", f.Name())
48
	cmd := exec.Command("go", "run", f.Name())
59
	return cmd.CombinedOutput()
49
	return cmd.CombinedOutput()
60
}
50
}
61
51
52
func (l LanguageGo) Extension() string { return "go" }
53
54
func (l LanguagePython) RunFile(f *os.File) ([]byte, error) {
55
	cmd := exec.Command("python", f.Name())
56
	return cmd.CombinedOutput()
57
}
58
59
func (l LanguagePython) Extension() string { return "py" }
60
61
func Eval(lang Language, code string) ([]byte, error) {
62
	// write code to temp file
63
	f, err := writeCode(code, lang.Extension())
64
	defer f.Close()
65
	if err != nil {
66
		return nil, err
67
	}
68
	// `go run` it
69
	res, err := lang.RunFile(f)
70
	if err != nil {
71
		return res, err
72
	}
73
	// remove the file
74
	os.Remove(f.Name())
75
	// return output
76
	return res, nil
77
}
78
62
func runCodeHandler(w http.ResponseWriter, r *http.Request) {
79
func runCodeHandler(w http.ResponseWriter, r *http.Request) {
63
	code, err := ioutil.ReadAll(r.Body)
80
	code, err := ioutil.ReadAll(r.Body)
64
	if err != nil {
81
	if err != nil {
65
		http.Error(w, err.Error(), http.StatusBadRequest)
82
		http.Error(w, err.Error(), http.StatusBadRequest)
66
		return
83
		return
67
	}
84
	}
68
	//fmt.Println(string(code))
69
	res, err := Go.Eval(string(code))
85
	lang := getLanguage(r)
86
	res, err := Eval(lang, string(code))
70
	if err != nil {
87
	if err != nil {
71
		http.Error(w, string(res), http.StatusNotAcceptable)
88
		http.Error(w, string(res), http.StatusNotAcceptable)
72
		return
89
		return
74
	w.Write(res)
91
	w.Write(res)
75
}
92
}
76
93
94
func getLanguage(r *http.Request) Language {
95
	langName := r.URL.Query().Get("language")
96
	if langName != "" {
97
		lang, ok := languageMappings[langName]
98
		if ok {
99
			return lang
100
		}
101
	}
102
	return Go
103
}
104
77
func homePageHandler(w http.ResponseWriter, r *http.Request) {
105
func homePageHandler(w http.ResponseWriter, r *http.Request) {
78
	homePageTemplate.Execute(w, nil)
106
	homePageTemplate.Execute(w, nil)
79
}
107
}