From 43e83607c0f0e34a1ba679b7001429da008c0c55 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Thu, 28 Nov 2019 17:39:35 +0000 Subject: [PATCH] initial commit --- Dockerfile | 21 +++ LICENSE | 12 ++ compile.go | 105 +++++++++++++ go.mod | 14 ++ go.sum | 148 +++++++++++++++++++ http.go | 423 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 134 +++++++++++++++++ run.go | 73 +++++++++ version.go | 13 ++ 9 files changed, 943 insertions(+) create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 compile.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 http.go create mode 100644 main.go create mode 100644 run.go create mode 100644 version.go diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..86267a9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM xena/go:1.13.3 AS build +WORKDIR /hlang +COPY . . +RUN GOBIN=/usr/local/bin go install . + +FROM xena/alpine AS wasm +WORKDIR /wabt +RUN apk --no-cache add build-base cmake git python \ + && git clone --recursive https://github.com/WebAssembly/wabt /wabt \ + && mkdir build \ + && cd build \ + && cmake .. \ + && make && make install +RUN ldd $(which wat2wasm) + +FROM xena/alpine +COPY --from=wasm /usr/local/bin/wat2wasm /usr/local/bin/wat2wasm +COPY --from=build /usr/local/bin/hlang /usr/local/bin/hlang +ENV PORT 5000 +RUN apk --no-cache add libstdc++ +CMD /usr/local/bin/hlang diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..87df039 --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2019 Christine Dodrill + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/compile.go b/compile.go new file mode 100644 index 0000000..a2077da --- /dev/null +++ b/compile.go @@ -0,0 +1,105 @@ +package main + +import ( + "bytes" + "context" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "text/template" + "time" + + "github.com/eaburns/peggy/peg" + "within.website/x/h" +) + +var ( + wat2wasmLoc string + wasmTemplateObj *template.Template +) + +func init() { + loc, err := exec.LookPath("wat2wasm") + if err != nil { + panic(err) + } + + wat2wasmLoc = loc + wasmTemplateObj = template.Must(template.New("h.wast").Parse(wasmTemplate)) +} + +// CompiledProgram is a fully parsed and compiled h program. +type CompiledProgram struct { + Source string `json:"src"` + WebAssemblyText string `json:"wat"` + Binary []byte `json:"bin"` + AST string `json:"ast"` +} + +func compile(source string) (*CompiledProgram, error) { + tree, err := h.Parse(source) + if err != nil { + return nil, err + } + + var sb strings.Builder + err = peg.PrettyWrite(&sb, tree) + + result := CompiledProgram{ + Source: source, + AST: sb.String(), + } + + dir, err := ioutil.TempDir("", "h") + if err != nil { + return nil, err + } + defer os.RemoveAll(dir) + + fout, err := os.Create(filepath.Join(dir, "h.wast")) + if err != nil { + return nil, err + } + + buf := bytes.NewBuffer(nil) + + err = wasmTemplateObj.Execute(buf, []byte(tree.Text)) + if err != nil { + return nil, err + } + + result.WebAssemblyText = buf.String() + _, err = fout.WriteString(result.WebAssemblyText) + if err != nil { + return nil, err + } + + fname := fout.Name() + + err = fout.Close() + if err != nil { + return nil, err + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + cmd := exec.CommandContext(ctx, wat2wasmLoc, fname, "-o", filepath.Join(dir, "h.wasm")) + cmd.Dir = dir + + err = cmd.Run() + if err != nil { + return nil, err + } + + data, err := ioutil.ReadFile(filepath.Join(dir, "h.wasm")) + if err != nil { + return nil, err + } + + result.Binary = data + + return &result, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..237d372 --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module tulpa.dev/cadey/hlang + +go 1.13 + +replace github.com/go-interpreter/wagon v0.0.0 => github.com/perlin-network/wagon v0.3.1-0.20180825141017-f8cb99b55a39 + +require ( + github.com/eaburns/peggy v1.0.1 + github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456 + github.com/perlin-network/life v0.0.0-20191010061010-fa85cafea8ac + github.com/rs/cors v1.7.0 + within.website/ln v0.7.0 + within.website/x v1.1.8 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4efb829 --- /dev/null +++ b/go.sum @@ -0,0 +1,148 @@ +bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +git.xeserv.us/xena/jvozba v0.0.0-20190616002803-f274e24d1e52/go.mod h1:lPdeNnexyxX+GQt62HV9UypJDg9enMwadWLXazGUUuc= +github.com/McKael/madon/v2 v2.0.0-20180929094633-c679abc985d6/go.mod h1:mvlJhxZCchfiasx3XvN3hBu5RekGwTDm09dKlSM/dQQ= +github.com/Yawning/bulb v0.0.0-20170405033506-85d80d893c3d/go.mod h1:v1YQIDSfaeRRehor57unRn66SBtmgAzxfsCpKIV998I= +github.com/aclements/go-moremath v0.0.0-20190506201756-286cc0be6f75/go.mod h1:idZL3yvz4kzx1dsBOAC+oYv6L92P1oFEhUXUB1A/lwQ= +github.com/birkelund/boltdbcache v1.0.0/go.mod h1:WgJWF40tV+4K0Q7MxAPbWEIkgs4AVUB7EyKVds0EgfQ= +github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= +github.com/celrenheit/sandflake v0.0.0-20190410195419-50a943690bc2 h1:/BpnZPo/sk1vPlt62dLya5KCn7PN9ZBDrpTGlQzgUZI= +github.com/celrenheit/sandflake v0.0.0-20190410195419-50a943690bc2/go.mod h1:7L8gY0+4GYeBc9TvqVuDUq7tXuM6Sj7llnt7HkVwWlQ= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-failure v0.0.0-20151001134759-4963dbd58fd0/go.mod h1:vVcpVd0tzL5XdRrkHax1asNJsHVpgA0cd9fHPHU5a/w= +github.com/dgryski/go-onlinestats v0.0.0-20170612111826-1c7d19468768/go.mod h1:alfmlCqcg4uw9jaoIU1nOp9RFdJLMuu8P07BCEgpgoo= +github.com/disintegration/imaging v1.6.0/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ= +github.com/eaburns/peggy v0.0.0-20180405011029-d685ddd3cbcb/go.mod h1:5tfPwI6ukiK3W5vJzkj5MBQKHHY9Gcy2y6k1FC/23Xk= +github.com/eaburns/peggy v0.0.0-20190420135231-b61cdde6efe6/go.mod h1:5tfPwI6ukiK3W5vJzkj5MBQKHHY9Gcy2y6k1FC/23Xk= +github.com/eaburns/peggy v1.0.1 h1:13lzoWg0eTeVouHrqFxO3ZL/XT8YlVk8YBAe/IO9VAQ= +github.com/eaburns/peggy v1.0.1/go.mod h1:X2pbl0EV5erfnK8kSGwo0lBCgMGokvR1E6KerAoDKXg= +github.com/eaburns/pretty v0.0.0-20170305202417-362524b72369/go.mod h1:iW/TU1T4mA4w2KzqNbBCjacPFdJ9PfGvNSxr8ajT/iM= +github.com/eaburns/pretty v0.0.0-20190404101635-2e1d2550ef0b/go.mod h1:iW/TU1T4mA4w2KzqNbBCjacPFdJ9PfGvNSxr8ajT/iM= +github.com/eaburns/pretty v1.0.0/go.mod h1:retcK8A0KEgdmb0nuxhvyxixwCmEPO7SKlK0IJhjg8A= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456 h1:CkmB2l68uhvRlwOTPrwnuitSxi/S3Cg4L5QYOcL9MBc= +github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456/go.mod h1:zFhibDvPDWmtk4dAQ05sRobtyoffEHygEt3wSNuAzz8= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/primitive v0.0.0-20190214200932-673f57e7b1b5/go.mod h1:Tm6t8LbdhSCXNfpjTwoL1mdjCnyKHkMyf6PqQXo7Or8= +github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/go-interpreter/wagon v0.6.0 h1:BBxDxjiJiHgw9EdkYXAWs8NHhwnazZ5P2EWBW5hFNWw= +github.com/go-interpreter/wagon v0.6.0/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hullerob/go.farbfeld v0.0.0-20181222022525-3661193c725f/go.mod h1:mQEoc766DxPTAwQ54neWTK/lFqIeSO7OU6bqZsceglw= +github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= +github.com/joeshaw/envdecode v0.0.0-20180312135643-c9e015854467/go.mod h1:Q+alOFAXgW5SrcfMPt/G4B2oN+qEcQRJjkn/f4mKL04= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mmikulicic/stringlist v1.0.0/go.mod h1:19Brp+Rld8TLwZ2oCHvTE3xDhCMr0jSCWwzcc9ejZgQ= +github.com/mndrix/golog v0.0.0-20170330170653-a28e2a269775/go.mod h1:Q4YHYl483MNk6wwg3g8YsINpKe5S2UzUJCRSRlFaSU0= +github.com/mndrix/ps v0.0.0-20170330174427-18e65badd6ab/go.mod h1:dHgTaDInzkAqJv67VaX1IkK449M2UoBY68CZeI/bNCU= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= +github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= +github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/perlin-network/life v0.0.0-20190625155037-103174020946/go.mod h1:z/EH0mO9zbeuTT5NX4u2VqVSG8y2vDQXz6iDKxikW2I= +github.com/perlin-network/life v0.0.0-20191010061010-fa85cafea8ac h1:JzeusmLSGyrRwaLEcZVCxskqNUUB1EyFswfh8ziRsto= +github.com/perlin-network/life v0.0.0-20191010061010-fa85cafea8ac/go.mod h1:tyABMoiJ4j//85N+bm67pYxi9nY3qKLydAFVzdsrLLY= +github.com/perlin-network/wagon v0.3.1-0.20180825141017-f8cb99b55a39/go.mod h1:zHOMvbitcZek8oshsMO5VpyBjWjV9X8cn8WTZwdebpM= +github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/sendgrid/rest v2.4.1+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= +github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= +github.com/streamrail/concurrent-map v0.0.0-20160823150647-8bf1e9bacbf6/go.mod h1:yqDD2twFAqxvvH5gtpwwgLsj5L1kbNwtoPoDOwBzXcs= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/sycamoreone/orc v0.0.0-20150204213357-1627eaec2699/go.mod h1:SZJ3/DVrJnKZPTTwCb38i9XZQU0T1yDm7oulSUO87a8= +github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= +github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= +github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= +github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef/go.mod h1:WLFStEdnJXpjK8kd4qKLwQKX/1vrDzp5BcDyiZJBHJM= +github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A= +github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89/go.mod h1:ejwOYCjnDMyO5LXFXRARQJGBZ6xQJZ3rgAHE5drSuMM= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119/go.mod h1:/nuTSlK+okRfR/vnIPqR89fFKonnWPiZymN5ydRJkX8= +github.com/xtaci/kcp-go v5.4.2+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= +github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= +github.com/xtaci/smux v1.3.3/go.mod h1:f+nYm6SpuHMy/SH0zpbvAFHT1QoMcgLOsWcFip5KfPw= +github.com/yawning/bulb v0.0.0-20170405033506-85d80d893c3d/go.mod h1:2ickkGiASLFhjpaFnwRS1qr2yaY7EgGk73v+DIOL5Bo= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go4.org v0.0.0-20190313082347-94abd6928b1d h1:JkRdGP3zvTtTbabWSAC6n67ka30y7gOzWAah4XYJSfw= +go4.org v0.0.0-20190313082347-94abd6928b1d/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp/errors v0.0.0-20190510132918-efd6b22b2522/go.mod h1:YgqsNsAu4fTvlab/7uiYK9LJrCIzKg/NiZUIH1/ayqo= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190523182746-aaccbc9213b0/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190219203350-90b0e4468f99/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/tucnak/telebot.v2 v2.0.0-20190415090633-8c1c512262f2/go.mod h1:+//wyPtHTeW2kfyEBwB05Hqnxev7AGrsLIyylSH++KU= +within.website/confyg v0.4.0 h1:FklkpJyMLYBxECCI4RS4R2c/x7PblOvbX0qBjk8Wkjs= +within.website/confyg v0.4.0/go.mod h1:KD5rDgkE3B+vbDiH/usiuK+CfiOkCiuD87NEF3/budk= +within.website/johaus v1.1.0/go.mod h1:0RBs2TucQ3CZQiVoqNj9Wch7mtZY05uvNO14v0lKcM4= +within.website/ln v0.6.0/go.mod h1:ifURKqsCJekcsdUE+hyCdcuhQqQ+9v9DfA++ZqYxZFE= +within.website/ln v0.7.0 h1:cZUc53cZF/+hWuEAv1VbqlYJ5czuPFHKfH0hLKmlIUA= +within.website/ln v0.7.0/go.mod h1:ifURKqsCJekcsdUE+hyCdcuhQqQ+9v9DfA++ZqYxZFE= +within.website/x v1.1.8 h1:OSiR9OQo+nRf17tiZV559bgKFB7x6xfcjPj9vVcJxVo= +within.website/x v1.1.8/go.mod h1:L6lqE0SSvN7RMnVFMuKsArOEzuRkT1R2HKYJgu/un7Q= diff --git a/http.go b/http.go new file mode 100644 index 0000000..b95ba18 --- /dev/null +++ b/http.go @@ -0,0 +1,423 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "net/http" + + "github.com/rs/cors" + "within.website/ln/ex" +) + +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("/", doTemplate(indexTemplate)) + http.Handle("/docs", doTemplate(docsTemplate)) + http.Handle("/faq", doTemplate(faqTemplate)) + http.Handle("/play", doTemplate(playgroundTemplate)) + http.HandleFunc("/api/playground", runPlayground) + + return http.ListenAndServe(":"+*port, ex.HTTPLog(cors.Default().Handler(http.DefaultServeMux))) +} + +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(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 *ExecResult `json:"res"` + }{ + Program: comp, + Results: er, + }) +} + +func doTemplate(body string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + fmt.Fprintln(w, body) + }) +} + +const indexTemplate = ` + + The h Programming Language + + + + +
+ + +

The h Programming Language

+ +

A simple, fast, open-source, complete and safe language for developing modern software for the web

+ +
+ +

Example Program

+ +
h
+ +

Outputs:

+ +
h
+ +
+ +

Fast Compilation

+ +

h compiles hundreds of characters of source per second. I didn't really test how fast it is, but when I was testing it the speed was fast enough that I didn't care to profile it.

+ +
+ +

Safety

+ +

h is completely memory safe with no garbage collector or heap allocations. It does not allow memory leaks to happen, nor do any programs in h have the possibility to allocate memory.

+ +
    +
  • No null
  • +
  • Completely deterministic behavior
  • +
  • No mutable state
  • +
  • No persistence
  • +
  • All functions are pure functions
  • +
  • No sandboxing required
  • +
+ +
+ +

Zero* Dependencies

+ +

h generates WebAssembly, so every binary produced by the compiler is completely dependency free save a single system call: h.h. This allows for modern, future-proof code that will work on all platforms.

+ +
+ +

Simple

+ +

h has a simple grammar that gzips to 117 bytes. Creating a runtime environment for h is so trivial just about anyone can do it.

+ +
+ +

Platform Support

+ +

h supports the following platforms:

+ +
    +
  • Google Chrome
  • +
  • Electron
  • +
  • Chromium Embedded Framework
  • +
  • Microsoft Edge
  • +
  • Olin
  • +
+ +
+ +

International Out of the Box

+ +

h supports multiple written and spoken languages with true contextual awareness. It not only supports the Latin h as input, it also accepts the Lojbanic ' as well. This allows for full 100% internationalization into Lojban should your project needs require it.

+ +
+ +

Testimonials

+ +

Not convinced? Take the word of people we probably didn't pay for their opinion.

+ +
    +
  • I don't see the point of this.
  • +
  • This solves all my problems. All of them. Just not in the way I expected it to.
  • +
  • Yes.
  • +
  • Perfect.
  • +
  • h is the backbone of my startup.
  • +
+ +
+ +

Open-Source

+ +

The h compiler and default runtime are open-source free software sent out into the Public Domain. You can use h for any purpose at all with no limitations or restrictions.

+ +
+ + +
+ +` + +const docsTemplate = ` + + The h Programming Language - Docs + + + + +
+ + +

Documentation

+ +

Coming soon...

+ + +
+ + +
+ +` + +const faqTemplate = ` + + The h Programming Language - FAQ + + + + +
+ + +

Frequently Asked Questions

+ +

What are the instructions of h?

+ +

h supports the following instructions:

+
    +
  • h
  • +
  • '
  • +
+ +

All valid h instructions must be separated by a space (\0x20 or the spacebar on your computer). No other forms of whitespace are permitted. Any other characters will render your program gentoldra.

+ +

How do I install and use h?

+ +

With any computer running Go 1.11 or higher:

+ +
go get -u -v within.website/x/cmd/h
+ + Usage is simple: + +
Usage of h:
+  -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
+  -o-wat string
+        if specified, write the uncompiled webassembly
+        created by -p here
+  -p string
+        h program to compile/run
+  -port string
+        HTTP port to listen on
+  -v    if true, print the version of h and then exit
+ +

What version is h?

+ +

Version 1.0, this will hopefully be the only release.

+ +

What is the h koan?

+ +

And Jesus said unto the theologians, "Who do you say that I am?"

+ +

They replied: "You are the eschatological manifestation of the ground of our being, the kerygma of which we find the ultimate meaning in our interpersonal relationships."

+ +

And Jesus said "...What?"

+ +

Some time passed and one of them spoke "h".

+ +

Jesus was enlightened.

+ +

Why?

+ +

That's a good question. The following blogposts may help you understand this more:

+ + + +

Who wrote h?

+ +

Within

+ +
+ + +
+ +` + +const playgroundTemplate = ` + + The h Programming Language - Playground + + + + +
+ + +

Playground

+ +

Unfortunately, Javascript is required to use this page, sorry.

+ +

Program

+ + + + +

+ +

Output

+ +
+ +

WebAssembly Text Format

+ +
+ +

Gas used:

+

Execution time (nanoseconds):

+ +

AST

+ +
+ + + +
+ + +
+ +` diff --git a/main.go b/main.go new file mode 100644 index 0000000..9a22a2a --- /dev/null +++ b/main.go @@ -0,0 +1,134 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" + + "github.com/facebookgo/flagenv" +) + +var _ = func() error { log.SetFlags(log.LstdFlags | log.Llongfile); return nil }() + +var ( + program = flag.String("p", "", "h program to compile/run") + outFname = flag.String("o", "", "if specified, write the webassembly binary created by -p here") + watFname = flag.String("o-wat", "", "if specified, write the uncompiled webassembly created by -p here") + port = flag.String("port", "", "HTTP port to listen on") + writeTao = flag.Bool("koan", false, "if true, print the h koan and then exit") + writeVersion = flag.Bool("v", false, "if true, print the version of h and then exit") +) + +const koan = `And Jesus said unto the theologians, "Who do you say that I am?" + +They replied: "You are the eschatological manifestation of the ground of our +being, the kerygma of which we find the ultimate meaning in our interpersonal +relationships." + +And Jesus said "...What?" + +Some time passed and one of them spoke "h". + +Jesus was enlightened.` + +func tao() { + fmt.Println(koan) + os.Exit(0) +} + +func oneOff() error { + log.Println("compiling...") + comp, err := compile(*program) + if err != nil { + return err + } + + log.Println("running...") + er, err := run(comp.Binary) + if err != nil { + return err + } + + log.Println("success!") + + log.Printf("gas used:\t%d", er.GasUsed) + log.Printf("exec time:\t%s", er.ExecTime) + log.Println("output:") + fmt.Print(er.Output) + + if *outFname != "" { + err := ioutil.WriteFile(*outFname, comp.Binary, 0666) + if err != nil { + return err + } + + log.Printf("wrote %d bytes to %s", len(comp.Binary), *outFname) + } + + if *watFname != "" { + err := ioutil.WriteFile(*watFname, []byte(comp.WebAssemblyText), 0666) + if err != nil { + return err + } + + log.Printf("write %d bytes of source to %s", len(comp.WebAssemblyText), *watFname) + } + + return nil +} + +func main() { + flagenv.Parse() + flag.Parse() + + if *writeVersion { + dumpVersion() + } + + if *writeTao { + tao() + } + + if *program != "" { + err := oneOff() + if err != nil { + panic(err) + } + + return + } + + if *port != "" { + err := doHTTP() + if err != nil { + panic(err) + } + + return + } +} + +const wasmTemplate = `(module + (import "h" "h" (func $h (param i32))) + (func $h_main + (local i32 i32 i32) + (local.set 0 (i32.const 10)) + (local.set 1 (i32.const 104)) + (local.set 2 (i32.const 39)) + {{ range . -}} + {{ if eq . 32 -}} + (call $h (get_local 0)) + {{ end -}} + {{ if eq . 104 -}} + (call $h (get_local 1)) + {{ end -}} + {{ if eq . 39 -}} + (call $h (get_local 2)) + {{ end -}} + {{ end -}} + (call $h (get_local 0)) + ) + (export "h" (func $h_main)) +)` diff --git a/run.go b/run.go new file mode 100644 index 0000000..fb55bb7 --- /dev/null +++ b/run.go @@ -0,0 +1,73 @@ +package main + +import ( + "errors" + "time" + + "github.com/perlin-network/life/compiler" + "github.com/perlin-network/life/exec" +) + +type Process struct { + Output []byte +} + +// ResolveGlobal does nothing, currently. +func (p *Process) ResolveGlobal(module, field string) int64 { return 0 } + +// ResolveFunc resolves h's ABI and importable function. +func (p *Process) ResolveFunc(module, field string) exec.FunctionImport { + switch module { + case "h": + switch field { + case "h": + return func(vm *exec.VirtualMachine) int64 { + frame := vm.GetCurrentFrame() + data := frame.Locals[0] + p.Output = append(p.Output, byte(data)) + + return 0 + } + + default: + panic("impossible state") + } + + default: + panic("impossible state") + } +} + +type ExecResult struct { + Output string `json:"out"` + GasUsed uint64 `json:"gas"` + ExecTime time.Duration `json:"exec_duration"` +} + +func run(bin []byte) (*ExecResult, error) { + p := &Process{} + + var cfg exec.VMConfig + gp := &compiler.SimpleGasPolicy{GasPerInstruction: 1} + vm, err := exec.NewVirtualMachine(bin, cfg, p, gp) + if err != nil { + return nil, err + } + + mainFunc, ok := vm.GetFunctionExport("h") + if !ok { + return nil, errors.New("impossible state: no h function exposed") + } + + t0 := time.Now() + _, err = vm.Run(mainFunc) + if err != nil { + return nil, err + } + + return &ExecResult{ + Output: string(p.Output), + GasUsed: vm.Gas, + ExecTime: time.Since(t0), + }, nil +} diff --git a/version.go b/version.go new file mode 100644 index 0000000..f321497 --- /dev/null +++ b/version.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + "os" +) + +const version = "1.0.0" + +func dumpVersion() { + fmt.Println("h programming language version", version) + os.Exit(0) +}