2019-11-28 17:39:35 +00:00
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
2021-04-02 12:02:10 +00:00
"net"
2019-11-28 17:39:35 +00:00
"net/http"
2021-04-02 12:02:10 +00:00
"os"
2019-11-28 17:39:35 +00:00
"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 )
2021-04-02 12:02:10 +00:00
srv := & http . Server {
Addr : ":" + * port ,
Handler : ex . HTTPLog ( cors . Default ( ) . Handler ( http . DefaultServeMux ) ) ,
}
if * sockpath != "" {
os . RemoveAll ( * sockpath )
l , err := net . Listen ( "unix" , * sockpath )
if err != nil {
return fmt . Errorf ( "can't listen on %s: %v" , * sockpath , err )
}
defer l . Close ( )
return srv . Serve ( l )
} else {
return srv . ListenAndServe ( )
}
2019-11-28 17:39:35 +00:00
}
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 >
2020-01-24 00:14:50 +00:00
< p > h has a < a href = "https://tulpa.dev/cadey/hlang/src/branch/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 >
2019-11-28 17:39:35 +00:00
< 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 >
2020-01-24 00:14:50 +00:00
< p > The h compiler and default runtime are < a href = "https://tulpa.dev/cadey/hlang" > 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 >
2019-11-28 17:39:35 +00:00
< 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 > `