commit 43e83607c0f0e34a1ba679b7001429da008c0c55 Author: Christine Dodrill Date: Thu Nov 28 17:39:35 2019 +0000 initial commit 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) +}