///|
#cfg(target="js")
extern "js" fn install_web_sdk(
run_source : (String, Int32) -> String,
evaluate_source : (String, Int32) -> String,
) -> Unit =
#| (runSource, evaluateSource) => {
#| const normalizeLimit = (value) => Number.isSafeInteger(value) && value > 0 ? value : 1000000;
#| globalThis.MoonWrenCore = Object.freeze({
#| version: "0.9.4",
#| runText(source, options = {}) {
#| return runSource(String(source), normalizeLimit(options.maxSteps));
#| },
#| evaluate(source, options = {}) {
#| return JSON.parse(evaluateSource(String(source), normalizeLimit(options.maxSteps)));
#| }
#| });
#| if (typeof document === "undefined") return;
#| const run = document.getElementById("run");
#| const source = document.getElementById("source");
#| const output = document.getElementById("output");
#| const status = document.getElementById("status");
#| const picker = document.getElementById("example");
#| if (!run || !source || !output || !status || !picker) return;
#| const initial = source.value;
#| const examples = {
#| sum: initial,
#| collections: 'var values = [3, 1, 2]\nvalues.sort()\nSystem.print(values)\nvar map = {"answer": 42}\nSystem.print(map["answer"])',
#| fiber: 'var worker = Fiber.new {\n System.print("started")\n Fiber.yield("paused")\n return "finished"\n}\nSystem.print(worker.call())\nSystem.print(worker.call())',
#| unicode: 'var text = "你好, MoonWren"\nSystem.print(text.count)\nSystem.print(text.bytes.count)\nSystem.print(text[0])'
#| };
#| const execute = () => {
#| const started = performance.now();
#| output.textContent = globalThis.MoonWrenCore.runText(source.value);
#| status.textContent = "Finished in " + (performance.now() - started).toFixed(1) + " ms";
#| };
#| run.addEventListener("click", execute);
#| document.getElementById("reset").addEventListener("click", () => { source.value = initial; picker.value = "sum"; history.replaceState(null, "", location.pathname + location.search); execute(); });
#| picker.addEventListener("change", () => { source.value = examples[picker.value]; execute(); });
#| source.addEventListener("keydown", (event) => { if ((event.ctrlKey || event.metaKey) && event.key === "Enter") { event.preventDefault(); execute(); } });
#| document.getElementById("share").addEventListener("click", async () => {
#| const url = new URL(location.href); url.hash = encodeURIComponent(source.value);
#| history.replaceState(null, "", url);
#| try { await navigator.clipboard.writeText(url.href); status.textContent = "Share link copied"; }
#| catch (_) { status.textContent = "Share link is ready in the address bar"; }
#| });
#| if (location.hash.length > 1) { try { source.value = decodeURIComponent(location.hash.slice(1)); picker.value = ""; } catch (_) {} }
#| execute();
#| }
///|
#cfg(target="js")
fn render(source : String, max_steps : Int32) -> String {
match @moonwren.run_with_limit(source, max_steps) {
@moonwren.ProgramCompleted(value, output) => {
let lines : Array[String] = []
for line in output {
lines.push(line)
}
lines.push("=> " + value.to_text())
lines.join("\n")
}
@moonwren.ProgramFailed(issues, output) => {
let lines : Array[String] = []
for line in output {
lines.push(line)
}
for issue in issues {
lines.push(issue.render("playground"))
}
lines.join("\n")
}
}
}
///|
#cfg(target="js")
fn evaluate_json(source : String, max_steps : Int32) -> String {
let document : Map[String, Json] = Map([])
match @moonwren.run_with_limit(source, max_steps) {
@moonwren.ProgramCompleted(value, output) => {
let output_json : Array[Json] = []
for line in output {
output_json.push(Json::string(line))
}
document["ok"] = Json::boolean(true)
document["value"] = Json::string(value.to_text())
document["output"] = Json::array(output_json)
document["diagnostics"] = Json::array([])
}
@moonwren.ProgramFailed(issues, output) => {
let diagnostics : Array[Json] = []
let output_json : Array[Json] = []
for line in output {
output_json.push(Json::string(line))
}
for issue in issues {
let entry : Map[String, Json] = Map([])
entry["message"] = Json::string(issue.message)
entry["rendered"] = Json::string(issue.render("sdk"))
entry["line"] = Json::number(issue.span.start.line.to_double())
entry["column"] = Json::number(issue.span.start.column.to_double())
diagnostics.push(Json::object(entry))
}
document["ok"] = Json::boolean(false)
document["value"] = Json::null()
document["output"] = Json::array(output_json)
document["diagnostics"] = Json::array(diagnostics)
}
}
Json::object(document).stringify()
}
///|
#cfg(target="js")
fn main {
install_web_sdk(render, evaluate_json)
}
///|
#cfg(not(target="js"))
fn main {
ignore(@moonwren.run("null"))
println("Build this package with --target js and open web/index.html.")
}