initial commit
This commit is contained in:
commit
43e83607c0
|
@ -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
|
|
@ -0,0 +1,12 @@
|
|||
Copyright (c) 2019 Christine Dodrill <me@christine.website>
|
||||
|
||||
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.
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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=
|
|
@ -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 = `<html>
|
||||
<head>
|
||||
<title>The h Programming Language</title>
|
||||
<link rel="stylesheet" href="https://within.website/static/gruvbox.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<nav>
|
||||
<a href="/">The h Programming Language</a> -
|
||||
<a href="/docs">Docs</a> -
|
||||
<a href="/play">Playground</a> -
|
||||
<a href="/faq">FAQ</a>
|
||||
</nav>
|
||||
|
||||
<h1>The h Programming Language</h1>
|
||||
|
||||
<p><big>A simple, fast, open-source, complete and safe language for developing modern software for the web</big></p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Example Program</h2>
|
||||
|
||||
<code><pre>h</pre></code>
|
||||
|
||||
<p>Outputs:</p>
|
||||
|
||||
<code><pre>h</pre></code>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Fast Compilation</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Safety</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<ul>
|
||||
<li>No null</li>
|
||||
<li>Completely deterministic behavior</li>
|
||||
<li>No mutable state</li>
|
||||
<li>No persistence</li>
|
||||
<li>All functions are pure functions</li>
|
||||
<li>No sandboxing required</li>
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Zero* Dependencies</h2>
|
||||
|
||||
<p>h generates <a href="http://webassembly.org">WebAssembly</a>, so every binary produced by the compiler is completely dependency free save a single system call: <code>h.h</code>. This allows for modern, future-proof code that will work on all platforms.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Simple</h2>
|
||||
|
||||
<p>h has a <a href="https://github.com/Xe/x/blob/master/h/h.peg">simple grammar</a> that gzips to 117 bytes. Creating a runtime environment for h is so trivial just about anyone can do it.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Platform Support</h2>
|
||||
|
||||
<p>h supports the following platforms:</p>
|
||||
|
||||
<ul>
|
||||
<li>Google Chrome</li>
|
||||
<li>Electron</li>
|
||||
<li>Chromium Embedded Framework</li>
|
||||
<li>Microsoft Edge</li>
|
||||
<li>Olin</li>
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>International Out of the Box</h2>
|
||||
|
||||
<p>h supports multiple written and spoken languages with true contextual awareness. It not only supports the Latin <code>h</code> as input, it also accepts the <a href="http://lojban.org">Lojbanic</a> <code>'</code> as well. This allows for full 100% internationalization into Lojban should your project needs require it.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Testimonials</h2>
|
||||
|
||||
<p>Not convinced? Take the word of people we probably didn't pay for their opinion.</p>
|
||||
|
||||
<ul>
|
||||
<li>I don't see the point of this.</li>
|
||||
<li>This solves all my problems. All of them. Just not in the way I expected it to.</li>
|
||||
<li>Yes.</li>
|
||||
<li>Perfect.</li>
|
||||
<li>h is the backbone of my startup.</li>
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Open-Source</h2>
|
||||
|
||||
<p>The h compiler and default runtime are <a href="https://github.com/Xe/x/tree/master/cmd/h">open-source</a> free software sent out into the <a href="https://creativecommons.org/choose/zero/">Public Domain</a>. You can use h for any purpose at all with no limitations or restrictions.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<footer>
|
||||
<center><p><i>From <a href="https://christine.website">Within</a></i></p></center>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
const docsTemplate = `<html>
|
||||
<head>
|
||||
<title>The h Programming Language - Docs</title>
|
||||
<link rel="stylesheet" href="https://within.website/static/gruvbox.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<nav>
|
||||
<a href="/">The h Programming Language</a> -
|
||||
<a href="/docs">Docs</a> -
|
||||
<a href="/play">Playground</a> -
|
||||
<a href="/faq">FAQ</a>
|
||||
</nav>
|
||||
|
||||
<h1>Documentation</h1>
|
||||
|
||||
<p><big id="comingsoon">Coming soon...</big></p>
|
||||
<script>
|
||||
Date.prototype.addDays = function(days) {
|
||||
var date = new Date(this.valueOf());
|
||||
date.setDate(date.getDate() + days);
|
||||
return date;
|
||||
}
|
||||
|
||||
let date = new Date();
|
||||
date = date.addDays(1);
|
||||
document.getElementById("comingsoon").innerHTML = "Coming " + date.toDateString();
|
||||
</script>
|
||||
|
||||
<hr />
|
||||
|
||||
<footer>
|
||||
<center><p><i>From <a href="https://christine.website">Within</a></i></p></center>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
const faqTemplate = `<html>
|
||||
<head>
|
||||
<title>The h Programming Language - FAQ</title>
|
||||
<link rel="stylesheet" href="https://within.website/static/gruvbox.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<nav>
|
||||
<a href="/">The h Programming Language</a> -
|
||||
<a href="/docs">Docs</a> -
|
||||
<a href="/play">Playground</a> -
|
||||
<a href="/faq">FAQ</a>
|
||||
</nav>
|
||||
|
||||
<h1>Frequently Asked Questions</h1>
|
||||
|
||||
<h2>What are the instructions of h?</h2>
|
||||
|
||||
<p>h supports the following instructions:</p>
|
||||
<ul>
|
||||
<li><code>h</code></li>
|
||||
<li><code>'</code></li>
|
||||
</ul>
|
||||
|
||||
<p>All valid h instructions must be separated by a space (<code>\0x20</code> or the spacebar on your computer). No other forms of whitespace are permitted. Any other characters will render your program <a href="http://jbovlaste.lojban.org/dict/gentoldra">gentoldra</a>.</p>
|
||||
|
||||
<h2>How do I install and use h?</h2>
|
||||
|
||||
<p>With any computer running <a href="https://golang.org">Go</a> 1.11 or higher:</p>
|
||||
|
||||
<code><pre>go get -u -v within.website/x/cmd/h</pre></code>
|
||||
|
||||
Usage is simple:
|
||||
|
||||
<code><pre>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</pre></code>
|
||||
|
||||
<h2>What version is h?</h2>
|
||||
|
||||
<p>Version 1.0, this will hopefully be the only release.</p>
|
||||
|
||||
<h2>What is the h koan?</h2>
|
||||
|
||||
<p>And Jesus said unto the theologians, "Who do you say that I am?"</p>
|
||||
|
||||
<p>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."</p>
|
||||
|
||||
<p>And Jesus said "...What?"</p>
|
||||
|
||||
<p>Some time passed and one of them spoke "h".</p>
|
||||
|
||||
<p>Jesus was enlightened.</p>
|
||||
|
||||
<h2>Why?</h2>
|
||||
|
||||
<p>That's a good question. The following blogposts may help you understand this more:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://christine.website/blog/the-origin-of-h-2015-12-14">The Origin of h</a></li>
|
||||
<li><a href="https://christine.website/blog/formal-grammar-of-h-2019-05-19">A Formal Grammar of h</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>Who wrote h?</h2>
|
||||
|
||||
<p><a href="https://christine.website">Within</a></p>
|
||||
|
||||
<hr />
|
||||
|
||||
<footer>
|
||||
<center><p><i>From <a href="https://christine.website">Within</a></i></p></center>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
const playgroundTemplate = `<html>
|
||||
<head>
|
||||
<title>The h Programming Language - Playground</title>
|
||||
<link rel="stylesheet" href="https://within.website/static/gruvbox.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<nav>
|
||||
<a href="/">The h Programming Language</a> -
|
||||
<a href="/docs">Docs</a> -
|
||||
<a href="/play">Playground</a> -
|
||||
<a href="/faq">FAQ</a>
|
||||
</nav>
|
||||
|
||||
<h1>Playground</h1>
|
||||
|
||||
<p><small>Unfortunately, Javascript is required to use this page, sorry.</small></p>
|
||||
|
||||
<h2>Program</h2>
|
||||
|
||||
<input id="program" type="text" value="h" />
|
||||
|
||||
<input onClick="runProgram()" type="button" value="Run">
|
||||
<p id="status"></p>
|
||||
|
||||
<h3>Output</h3>
|
||||
|
||||
<code><pre id="output"></pre></code>
|
||||
|
||||
<h4>WebAssembly Text Format</h4>
|
||||
|
||||
<code><pre id="wat_box"></pre></code>
|
||||
|
||||
<p>Gas used: <span id="gas_used"></span></p>
|
||||
<p>Execution time (nanoseconds): <span id="exec_time"></span></p>
|
||||
|
||||
<h4>AST</h4>
|
||||
|
||||
<code><pre id="ast_box"></pre></code>
|
||||
|
||||
<script>
|
||||
function runProgram() {
|
||||
const programData = document.getElementById("program").value;
|
||||
const output = document.getElementById("output");
|
||||
const watBox = document.getElementById("wat_box");
|
||||
const astBox = document.getElementById("ast_box");
|
||||
const gasUsed = document.getElementById("gas_used");
|
||||
const execTime = document.getElementById("exec_time");
|
||||
const status = document.getElementById("status");
|
||||
|
||||
status.innerHTML = "submitting to the server...";
|
||||
|
||||
postData("/api/playground", programData)
|
||||
.then(function(data) {
|
||||
if (data.err != null) {
|
||||
status.innerHTML = data.err;
|
||||
return;
|
||||
}
|
||||
|
||||
status.innerHTML = "success";
|
||||
watBox.innerHTML = data.prog.wat;
|
||||
astBox.innerHTML = data.prog.ast;
|
||||
output.innerHTML = data.res.out;
|
||||
gasUsed.innerHTML = data.res.gas;
|
||||
execTime.innerHTML = data.res.exec_duration;
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.log(error);
|
||||
status.innerHTML = error + ". Please try again later?";
|
||||
});
|
||||
}
|
||||
|
||||
function postData(url = "", data = "h") {
|
||||
return fetch(url, {
|
||||
method: "POST",
|
||||
mode: "cors",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
referrer: "no-referrer",
|
||||
body: data,
|
||||
}).then(response => response.json());
|
||||
}
|
||||
</script>
|
||||
|
||||
<hr />
|
||||
|
||||
<footer>
|
||||
<center><p><i>From <a href="https://christine.website">Within</a></i></p></center>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>`
|
|
@ -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))
|
||||
)`
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
Loading…
Reference in New Issue