106 lines
3.1 KiB
Nim
106 lines
3.1 KiB
Nim
# playground.nim — Bux language web playground
|
|
# Uses hunos HTTP server to accept Bux code, compile with buxc, run, and return output
|
|
#
|
|
# Usage: nim c -r tools/playground.nim
|
|
# Then open http://localhost:8407 in browser
|
|
|
|
import std/[os, osproc, strutils, json]
|
|
import hunos, hunos/router
|
|
|
|
const
|
|
Buxc = "./buxc" # path to buxc binary
|
|
Port = 8407 # playground port
|
|
TimeoutMs = 5000 # max execution time (5 seconds)
|
|
|
|
# --------------- HTML frontend ---------------
|
|
const PlaygroundHTML = staticRead("playground.html")
|
|
|
|
# --------------- helpers ---------------
|
|
|
|
proc compileAndRun(code: string): tuple[output: string, exitCode: int, isError: bool] =
|
|
## Compile code with buxc, run the resulting binary, capture output.
|
|
var tmpDir = "/tmp/bux-playground-" & $getCurrentProcessId()
|
|
createDir(tmpDir)
|
|
createDir(tmpDir / "src")
|
|
|
|
# Write Main.bux
|
|
writeFile(tmpDir / "src" / "Main.bux", code)
|
|
|
|
# Write bux.toml
|
|
writeFile(tmpDir / "bux.toml", "[package]\nname = \"playground\"\nversion = \"0.1.0\"\ntype = \"bin\"\n\n[build]\noutput = \"Bin\"\n")
|
|
|
|
# Build with buxc
|
|
let buildResult = execCmdEx(Buxc & " build " & tmpDir)
|
|
let buildOutput = buildResult.output
|
|
|
|
if buildResult.exitCode != 0:
|
|
removeDir(tmpDir)
|
|
return (buildOutput, buildResult.exitCode, true)
|
|
|
|
# Run the binary (named "playground" from bux.toml)
|
|
let binary = tmpDir / "build" / "playground"
|
|
if not fileExists(binary):
|
|
removeDir(tmpDir)
|
|
return ("Binary not found after build:\n" & buildOutput, 1, true)
|
|
|
|
let runResult = execCmdEx("timeout " & $TimeoutMs div 1000 & " " & binary)
|
|
let runOutput = runResult.output
|
|
|
|
# Cleanup
|
|
removeDir(tmpDir)
|
|
|
|
return (buildOutput & "\n" & runOutput, runResult.exitCode, runResult.exitCode != 0)
|
|
|
|
# --------------- route handlers ---------------
|
|
|
|
proc handlePlayground(request: Request) =
|
|
var headers: HttpHeaders
|
|
headers["Content-Type"] = "text/html; charset=utf-8"
|
|
request.respond(200, headers, PlaygroundHTML)
|
|
|
|
proc handleCompile(request: Request) =
|
|
if request.httpMethod != HttpPost:
|
|
var headers: HttpHeaders
|
|
headers["Content-Type"] = "text/plain"
|
|
request.respond(405, headers, "Method not allowed")
|
|
return
|
|
|
|
let code = request.body
|
|
|
|
if code.len == 0:
|
|
var headers: HttpHeaders
|
|
headers["Content-Type"] = "application/json"
|
|
request.respond(400, headers, $(%*{"error": "no code provided"}))
|
|
return
|
|
|
|
let (output, exitCode, isError) = compileAndRun(code)
|
|
|
|
var headers: HttpHeaders
|
|
headers["Content-Type"] = "application/json"
|
|
headers["Access-Control-Allow-Origin"] = "*"
|
|
|
|
let response = $(%*{
|
|
"output": output,
|
|
"exitCode": exitCode,
|
|
"isError": isError
|
|
})
|
|
|
|
request.respond(200, headers, response)
|
|
|
|
# --------------- main ---------------
|
|
|
|
proc main() =
|
|
echo "Bux Playground"
|
|
echo "Serving on http://localhost:" & $Port
|
|
echo "Open your browser and start coding!"
|
|
|
|
var router: Router
|
|
router.get("/", handlePlayground)
|
|
router.post("/compile", handleCompile)
|
|
|
|
let server = newServer(router)
|
|
server.serve(Port(Port))
|
|
|
|
when isMainModule:
|
|
main()
|