1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"github.com/a-h/templ"
"github.com/rs/cors"
"within.website/x/cmd/hlang/h"
"within.website/x/cmd/hlang/run"
"within.website/x/xess"
)
//go:generate go tool templ generate
var (
maxBytes = flag.Int64("max-playground-bytes", 75, "how many bytes of data should users be allowed to post to the playground?")
)
func doHTTP() error {
http.Handle("/{$}", templ.Handler(xess.Base("The h Programming Language", nil, navbar(), homePage(), footer())))
http.Handle("/docs", templ.Handler(xess.Base("Documentation", nil, navbar(), docsPage(), footer())))
http.Handle("/faq", templ.Handler(xess.Base("FAQ", nil, navbar(), faqPage(), footer())))
http.Handle("/play", templ.Handler(xess.Base("Playground", nil, navbar(), playgroundPage(), footer())))
http.HandleFunc("/api/playground", runPlayground)
http.Handle("/grammar/", http.StripPrefix("/grammar/", http.FileServer(http.FS(h.Grammar))))
srv := &http.Server{
Addr: ":" + *port,
Handler: cors.Default().Handler(http.DefaultServeMux),
}
if *sockpath != "" {
os.RemoveAll(*sockpath)
l, err := net.Listen("unix", *sockpath)
if err != nil {
return fmt.Errorf("can't listen on %s: %v", *sockpath, err)
}
defer l.Close()
return srv.Serve(l)
} else {
return srv.ListenAndServe()
}
}
func httpError(w http.ResponseWriter, err error, code int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
json.NewEncoder(w).Encode(struct {
Error string `json:"err"`
}{
Error: err.Error(),
})
}
func runPlayground(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.NotFound(w, r)
return
}
rc := http.MaxBytesReader(w, r.Body, *maxBytes)
defer rc.Close()
data, err := ioutil.ReadAll(rc)
if err != nil {
httpError(w, err, http.StatusBadGateway)
return
}
comp, err := compile(string(data))
if err != nil {
httpError(w, fmt.Errorf("compliation error: %v", err), http.StatusBadRequest)
return
}
er, err := run.Run(comp.Binary)
if err != nil {
httpError(w, fmt.Errorf("runtime error: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(struct {
Program *CompiledProgram `json:"prog"`
Results *run.ExecResult `json:"res"`
}{
Program: comp,
Results: er,
})
}
const usage = `Usage of hlang:
-config string
configuration file, if set (see flagconfyg(4))
-koan
if true, print the h koan and then exit
-license
show software licenses?
-manpage
generate a manpage template?
-max-playground-bytes int
how many bytes of data should users be allowed to post to the playground? (default 75)
-o string
if specified, write the webassembly binary created by -p here
-p string
h program to compile/run
-port string
HTTP port to listen on
-slog-level string
log level (default "INFO")
-sockpath string
Unix domain socket to listen on
-v if true, print the version of h and then exit`
|