@@ 1,407 0,0 @@
-package.path = "./?.lua"
-local js = require("js")
-
--- minimal shims just to allow the compilers to load in Fengari
-package.loaded.ffi = {typeof=function() end}
-os = {getenv=function() end}
-io = {open=function() end}
-bit = {band = function(a,b) return a & b end,
- rshift=function(a,b) return a >> b end}
-unpack = table.unpack
-
-function print(...) js.global.console:log(...) end
-
-local document = js.global.document
-local compile_fennel = document:getElementById("compile-fennel")
-local compile_lua = document:getElementById("compile-lua")
-local out = document:getElementById("out")
-
-local fennel_source = document:getElementById("fennel-source")
-local fennel_highlighted = document:getElementById("fennel-highlighted")
-
-local lua_source = document:getElementById("lua-source")
-local lua_highlighted = document:getElementById("lua-highlighted")
-
-local status = function(msg, success)
- out.innerHTML = msg
- out.style.color = success and "black" or "#dd1111"
-end
-
--- Ctrl-enter to compile
-fennel_source.onkeydown = function(_, e)
- if not e then e = js.global.event end
- if (e.key or e.which) == "Enter" and e.ctrlKey then
- compile_fennel.onclick()
- return false
- end
-end
-
-lua_source.onkeydown = function(_,e)
- if not e then e = js.global.event end
- if (e.key or e.which) == "Enter" and e.ctrlKey then
- compile_lua.onclick()
- return false
- end
-end
-
--- Syntax highlighting is adapted from this guide:
--- https://css-tricks.com/creating-an-editable-textarea-that-supports-syntax-highlighted-code/
---
--- TL;DR: To highlight syntax in a user-editable textarea, we
--- 1. Copy the contents of the textarea on every edit
--- 2. Run the contents through a highlighting function to get styled HTML
--- 3. Set the HTML into a pre element that's just behind the textarea
--- 4. Make the textarea completely transparent except for the input caret
--- and ensure the input textarea and output pre have the same dimensions
--- using a bunch of CSS
-
-local syntax = {["#"] = {["special?"] = true}, ["%"] = {["special?"] = true}, ["*"] = {["special?"] = true}, ["+"] = {["special?"] = true}, ["-"] = {["special?"] = true}, ["->"] = {["macro?"] = true}, ["->>"] = {["macro?"] = true}, ["-?>"] = {["macro?"] = true}, ["-?>>"] = {["macro?"] = true}, ["."] = {["special?"] = true}, [".."] = {["special?"] = true}, ["/"] = {["special?"] = true}, ["//"] = {["special?"] = true}, [":"] = {["special?"] = true}, ["<"] = {["special?"] = true}, ["<="] = {["special?"] = true}, ["="] = {["special?"] = true}, [">"] = {["special?"] = true}, [">="] = {["special?"] = true}, ["?."] = {["macro?"] = true}, ["^"] = {["special?"] = true}, _G = {["global?"] = true}, __ = {["global?"] = true}, ___replLocals___ = {["global?"] = true}, accumulate = {["binding-form?"] = true, ["body-form?"] = true, ["macro?"] = true}, ["and"] = {["special?"] = true}, arg = {["global?"] = true}, assert = {["function?"] = true, ["global?"] = true}, band = {["special?"] = true}, bit32 = {["global?"] = true}, ["bit32.arshift"] = {["function?"] = true, ["global?"] = true}, ["bit32.band"] = {["function?"] = true, ["global?"] = true}, ["bit32.bnot"] = {["function?"] = true, ["global?"] = true}, ["bit32.bor"] = {["function?"] = true, ["global?"] = true}, ["bit32.btest"] = {["function?"] = true, ["global?"] = true}, ["bit32.bxor"] = {["function?"] = true, ["global?"] = true}, ["bit32.extract"] = {["function?"] = true, ["global?"] = true}, ["bit32.lrotate"] = {["function?"] = true, ["global?"] = true}, ["bit32.lshift"] = {["function?"] = true, ["global?"] = true}, ["bit32.replace"] = {["function?"] = true, ["global?"] = true}, ["bit32.rrotate"] = {["function?"] = true, ["global?"] = true}, ["bit32.rshift"] = {["function?"] = true, ["global?"] = true}, bnot = {["special?"] = true}, bor = {["special?"] = true}, bxor = {["special?"] = true}, case = {["body-form?"] = true, ["macro?"] = true}, ["case-try"] = {["body-form?"] = true, ["macro?"] = true}, collect = {["binding-form?"] = true, ["body-form?"] = true, ["macro?"] = true}, collectgarbage = {["function?"] = true, ["global?"] = true}, comment = {["body-form?"] = true, ["special?"] = true}, coroutine = {["global?"] = true}, ["coroutine.create"] = {["function?"] = true, ["global?"] = true}, ["coroutine.isyieldable"] = {["function?"] = true, ["global?"] = true}, ["coroutine.resume"] = {["function?"] = true, ["global?"] = true}, ["coroutine.running"] = {["function?"] = true, ["global?"] = true}, ["coroutine.status"] = {["function?"] = true, ["global?"] = true}, ["coroutine.wrap"] = {["function?"] = true, ["global?"] = true}, ["coroutine.yield"] = {["function?"] = true, ["global?"] = true}, debug = {["global?"] = true}, ["debug.debug"] = {["function?"] = true, ["global?"] = true}, ["debug.gethook"] = {["function?"] = true, ["global?"] = true}, ["debug.getinfo"] = {["function?"] = true, ["global?"] = true}, ["debug.getlocal"] = {["function?"] = true, ["global?"] = true}, ["debug.getmetatable"] = {["function?"] = true, ["global?"] = true}, ["debug.getregistry"] = {["function?"] = true, ["global?"] = true}, ["debug.getupvalue"] = {["function?"] = true, ["global?"] = true}, ["debug.getuservalue"] = {["function?"] = true, ["global?"] = true}, ["debug.sethook"] = {["function?"] = true, ["global?"] = true}, ["debug.setlocal"] = {["function?"] = true, ["global?"] = true}, ["debug.setmetatable"] = {["function?"] = true, ["global?"] = true}, ["debug.setupvalue"] = {["function?"] = true, ["global?"] = true}, ["debug.setuservalue"] = {["function?"] = true, ["global?"] = true}, ["debug.traceback"] = {["function?"] = true, ["global?"] = true}, ["debug.upvalueid"] = {["function?"] = true, ["global?"] = true}, ["debug.upvaluejoin"] = {["function?"] = true, ["global?"] = true}, ["do"] = {["body-form?"] = true, ["special?"] = true}, dofile = {["function?"] = true, ["global?"] = true}, doto = {["body-form?"] = true, ["macro?"] = true}, each = {["binding-form?"] = true, ["body-form?"] = true, ["special?"] = true}, error = {["function?"] = true, ["global?"] = true}, ["eval-compiler"] = {["body-form?"] = true, ["special?"] = true}, faccumulate = {["binding-form?"] = true, ["body-form?"] = true, ["macro?"] = true}, fcollect = {["binding-form?"] = true, ["body-form?"] = true, ["macro?"] = true}, fn = {["body-form?"] = true, ["define?"] = true, ["special?"] = true}, fnl = {["global?"] = true}, ["fnl.ast-source"] = {["function?"] = true, ["global?"] = true}, ["fnl.comment"] = {["function?"] = true, ["global?"] = true}, ["fnl.comment?"] = {["function?"] = true, ["global?"] = true}, ["fnl.compile"] = {["function?"] = true, ["global?"] = true}, ["fnl.compile-stream"] = {["function?"] = true, ["global?"] = true}, ["fnl.compile-string"] = {["function?"] = true, ["global?"] = true}, ["fnl.compile1"] = {["function?"] = true, ["global?"] = true}, ["fnl.compileStream"] = {["function?"] = true, ["global?"] = true}, ["fnl.compileString"] = {["function?"] = true, ["global?"] = true}, ["fnl.doc"] = {["function?"] = true, ["global?"] = true}, ["fnl.dofile"] = {["function?"] = true, ["global?"] = true}, ["fnl.eval"] = {["function?"] = true, ["global?"] = true}, ["fnl.gensym"] = {["function?"] = true, ["global?"] = true}, ["fnl.granulate"] = {["function?"] = true, ["global?"] = true}, ["fnl.install"] = {["function?"] = true, ["global?"] = true}, ["fnl.list"] = {["function?"] = true, ["global?"] = true}, ["fnl.list?"] = {["function?"] = true, ["global?"] = true}, ["fnl.load-code"] = {["function?"] = true, ["global?"] = true}, ["fnl.loadCode"] = {["function?"] = true, ["global?"] = true}, ["fnl.make-searcher"] = {["function?"] = true, ["global?"] = true}, ["fnl.makeSearcher"] = {["function?"] = true, ["global?"] = true}, ["fnl.make_searcher"] = {["function?"] = true, ["global?"] = true}, ["fnl.mangle"] = {["function?"] = true, ["global?"] = true}, ["fnl.multi-sym?"] = {["function?"] = true, ["global?"] = true}, ["fnl.parser"] = {["function?"] = true, ["global?"] = true}, ["fnl.repl"] = {["function?"] = true, ["global?"] = true}, ["fnl.runtime-version"] = {["function?"] = true, ["global?"] = true}, ["fnl.runtimeVersion"] = {["function?"] = true, ["global?"] = true}, ["fnl.scope"] = {["function?"] = true, ["global?"] = true}, ["fnl.search-module"] = {["function?"] = true, ["global?"] = true}, ["fnl.searchModule"] = {["function?"] = true, ["global?"] = true}, ["fnl.searcher"] = {["function?"] = true, ["global?"] = true}, ["fnl.sequence"] = {["function?"] = true, ["global?"] = true}, ["fnl.sequence?"] = {["function?"] = true, ["global?"] = true}, ["fnl.string-stream"] = {["function?"] = true, ["global?"] = true}, ["fnl.stringStream"] = {["function?"] = true, ["global?"] = true}, ["fnl.sym"] = {["function?"] = true, ["global?"] = true}, ["fnl.sym-char?"] = {["function?"] = true, ["global?"] = true}, ["fnl.sym?"] = {["function?"] = true, ["global?"] = true}, ["fnl.syntax"] = {["function?"] = true, ["global?"] = true}, ["fnl.table?"] = {["function?"] = true, ["global?"] = true}, ["fnl.traceback"] = {["function?"] = true, ["global?"] = true}, ["fnl.unmangle"] = {["function?"] = true, ["global?"] = true}, ["fnl.varg"] = {["function?"] = true, ["global?"] = true}, ["fnl.varg?"] = {["function?"] = true, ["global?"] = true}, ["fnl.view"] = {["function?"] = true, ["global?"] = true}, ["for"] = {["binding-form?"] = true, ["body-form?"] = true, ["special?"] = true}, getmetatable = {["function?"] = true, ["global?"] = true}, global = {["define?"] = true, ["special?"] = true}, hashfn = {["special?"] = true}, icollect = {["binding-form?"] = true, ["body-form?"] = true, ["macro?"] = true}, ["if"] = {["special?"] = true}, ["import-macros"] = {["macro?"] = true}, include = {["special?"] = true}, io = {["global?"] = true}, ["io.close"] = {["function?"] = true, ["global?"] = true}, ["io.flush"] = {["function?"] = true, ["global?"] = true}, ["io.input"] = {["function?"] = true, ["global?"] = true}, ["io.lines"] = {["function?"] = true, ["global?"] = true}, ["io.open"] = {["function?"] = true, ["global?"] = true}, ["io.output"] = {["function?"] = true, ["global?"] = true}, ["io.popen"] = {["function?"] = true, ["global?"] = true}, ["io.read"] = {["function?"] = true, ["global?"] = true}, ["io.tmpfile"] = {["function?"] = true, ["global?"] = true}, ["io.type"] = {["function?"] = true, ["global?"] = true}, ["io.write"] = {["function?"] = true, ["global?"] = true}, ipairs = {["function?"] = true, ["global?"] = true}, lambda = {["body-form?"] = true, ["define?"] = true, ["macro?"] = true}, length = {["special?"] = true}, let = {["binding-form?"] = true, ["body-form?"] = true, ["special?"] = true}, load = {["function?"] = true, ["global?"] = true}, loadfile = {["function?"] = true, ["global?"] = true}, ["local"] = {["define?"] = true, ["special?"] = true}, lshift = {["special?"] = true}, lua = {["special?"] = true}, macro = {["body-form?"] = true, ["define?"] = true, ["macro?"] = true}, macrodebug = {["macro?"] = true}, macros = {["define?"] = true, ["special?"] = true}, match = {["body-form?"] = true, ["macro?"] = true}, ["match-try"] = {["body-form?"] = true, ["macro?"] = true}, math = {["global?"] = true}, ["math.abs"] = {["function?"] = true, ["global?"] = true}, ["math.acos"] = {["function?"] = true, ["global?"] = true}, ["math.asin"] = {["function?"] = true, ["global?"] = true}, ["math.atan"] = {["function?"] = true, ["global?"] = true}, ["math.atan2"] = {["function?"] = true, ["global?"] = true}, ["math.ceil"] = {["function?"] = true, ["global?"] = true}, ["math.cos"] = {["function?"] = true, ["global?"] = true}, ["math.cosh"] = {["function?"] = true, ["global?"] = true}, ["math.deg"] = {["function?"] = true, ["global?"] = true}, ["math.exp"] = {["function?"] = true, ["global?"] = true}, ["math.floor"] = {["function?"] = true, ["global?"] = true}, ["math.fmod"] = {["function?"] = true, ["global?"] = true}, ["math.frexp"] = {["function?"] = true, ["global?"] = true}, ["math.ldexp"] = {["function?"] = true, ["global?"] = true}, ["math.log"] = {["function?"] = true, ["global?"] = true}, ["math.log10"] = {["function?"] = true, ["global?"] = true}, ["math.max"] = {["function?"] = true, ["global?"] = true}, ["math.min"] = {["function?"] = true, ["global?"] = true}, ["math.modf"] = {["function?"] = true, ["global?"] = true}, ["math.pow"] = {["function?"] = true, ["global?"] = true}, ["math.rad"] = {["function?"] = true, ["global?"] = true}, ["math.random"] = {["function?"] = true, ["global?"] = true}, ["math.randomseed"] = {["function?"] = true, ["global?"] = true}, ["math.sin"] = {["function?"] = true, ["global?"] = true}, ["math.sinh"] = {["function?"] = true, ["global?"] = true}, ["math.sqrt"] = {["function?"] = true, ["global?"] = true}, ["math.tan"] = {["function?"] = true, ["global?"] = true}, ["math.tanh"] = {["function?"] = true, ["global?"] = true}, ["math.tointeger"] = {["function?"] = true, ["global?"] = true}, ["math.type"] = {["function?"] = true, ["global?"] = true}, ["math.ult"] = {["function?"] = true, ["global?"] = true}, next = {["function?"] = true, ["global?"] = true}, ["not"] = {["special?"] = true}, ["not="] = {["special?"] = true}, ["or"] = {["special?"] = true}, os = {["global?"] = true}, ["os.clock"] = {["function?"] = true, ["global?"] = true}, ["os.date"] = {["function?"] = true, ["global?"] = true}, ["os.difftime"] = {["function?"] = true, ["global?"] = true}, ["os.execute"] = {["function?"] = true, ["global?"] = true}, ["os.exit"] = {["function?"] = true, ["global?"] = true}, ["os.getenv"] = {["function?"] = true, ["global?"] = true}, ["os.remove"] = {["function?"] = true, ["global?"] = true}, ["os.rename"] = {["function?"] = true, ["global?"] = true}, ["os.setlocale"] = {["function?"] = true, ["global?"] = true}, ["os.time"] = {["function?"] = true, ["global?"] = true}, ["os.tmpname"] = {["function?"] = true, ["global?"] = true}, package = {["global?"] = true}, ["package.loadlib"] = {["function?"] = true, ["global?"] = true}, ["package.searchpath"] = {["function?"] = true, ["global?"] = true}, pairs = {["function?"] = true, ["global?"] = true}, partial = {["macro?"] = true}, pcall = {["function?"] = true, ["global?"] = true}, ["pick-args"] = {["macro?"] = true}, ["pick-values"] = {["macro?"] = true}, print = {["function?"] = true, ["global?"] = true}, quote = {["special?"] = true}, rawequal = {["function?"] = true, ["global?"] = true}, rawget = {["function?"] = true, ["global?"] = true}, rawlen = {["function?"] = true, ["global?"] = true}, rawset = {["function?"] = true, ["global?"] = true}, require = {["function?"] = true, ["global?"] = true}, ["require-macros"] = {["special?"] = true}, rshift = {["special?"] = true}, select = {["function?"] = true, ["global?"] = true}, set = {["special?"] = true}, ["set-forcibly!"] = {["special?"] = true}, setmetatable = {["function?"] = true, ["global?"] = true}, string = {["global?"] = true}, ["string.byte"] = {["function?"] = true, ["global?"] = true}, ["string.char"] = {["function?"] = true, ["global?"] = true}, ["string.dump"] = {["function?"] = true, ["global?"] = true}, ["string.find"] = {["function?"] = true, ["global?"] = true}, ["string.format"] = {["function?"] = true, ["global?"] = true}, ["string.gmatch"] = {["function?"] = true, ["global?"] = true}, ["string.gsub"] = {["function?"] = true, ["global?"] = true}, ["string.len"] = {["function?"] = true, ["global?"] = true}, ["string.lower"] = {["function?"] = true, ["global?"] = true}, ["string.match"] = {["function?"] = true, ["global?"] = true}, ["string.pack"] = {["function?"] = true, ["global?"] = true}, ["string.packsize"] = {["function?"] = true, ["global?"] = true}, ["string.rep"] = {["function?"] = true, ["global?"] = true}, ["string.reverse"] = {["function?"] = true, ["global?"] = true}, ["string.sub"] = {["function?"] = true, ["global?"] = true}, ["string.unpack"] = {["function?"] = true, ["global?"] = true}, ["string.upper"] = {["function?"] = true, ["global?"] = true}, table = {["global?"] = true}, ["table.concat"] = {["function?"] = true, ["global?"] = true}, ["table.insert"] = {["function?"] = true, ["global?"] = true}, ["table.move"] = {["function?"] = true, ["global?"] = true}, ["table.pack"] = {["function?"] = true, ["global?"] = true}, ["table.remove"] = {["function?"] = true, ["global?"] = true}, ["table.sort"] = {["function?"] = true, ["global?"] = true}, ["table.unpack"] = {["function?"] = true, ["global?"] = true}, tonumber = {["function?"] = true, ["global?"] = true}, tostring = {["function?"] = true, ["global?"] = true}, tset = {["special?"] = true}, type = {["function?"] = true, ["global?"] = true}, utf8 = {["global?"] = true}, ["utf8.char"] = {["function?"] = true, ["global?"] = true}, ["utf8.codepoint"] = {["function?"] = true, ["global?"] = true}, ["utf8.codes"] = {["function?"] = true, ["global?"] = true}, ["utf8.len"] = {["function?"] = true, ["global?"] = true}, ["utf8.offset"] = {["function?"] = true, ["global?"] = true}, values = {["special?"] = true}, var = {["define?"] = true, ["special?"] = true}, when = {["body-form?"] = true, ["macro?"] = true}, ["while"] = {["body-form?"] = true, ["special?"] = true}, ["with-open"] = {["binding-form?"] = true, ["body-form?"] = true, ["macro?"] = true}, xpcall = {["function?"] = true, ["global?"] = true}, ["~="] = {["special?"] = true}, ["\206\187"] = {["body-form?"] = true, ["define?"] = true, ["macro?"] = true}}
-
-local function scan(text)
- local current_index = 1
- local last_matching_at = 0
- local text_length = string.len(text)
- local function at_eof_3f()
- return (current_index > text_length)
- end
- local function yield_buffered_nonmatching()
- if (0 < (current_index - last_matching_at)) then
- return coroutine.yield({kind = nil, value = string.sub(text, (last_matching_at + 1), (current_index - 1))})
- else
- return nil
- end
- end
- local function yield(kind, matched)
- yield_buffered_nonmatching()
- coroutine.yield({kind = kind, value = matched})
- current_index = (current_index + string.len(matched))
- last_matching_at = (current_index - 1)
- return nil
- end
- local function attempt_match(kind, pattern)
- local _2_ = string.match(text, pattern, current_index)
- if (nil ~= _2_) then
- local matched = _2_
- yield(kind, matched)
- return true
- else
- return nil
- end
- end
- local function increment_current_index()
- current_index = (current_index + 1)
- return nil
- end
- local symbol_char = "!%$&#%*%+%-%./:<=>%?%^_%w"
- while not at_eof_3f() do
- do local _ = (attempt_match("comment", "^(;[^\n]*[\n])") or attempt_match("string", "^(\"[^\"]*\")") or attempt_match("keyword", ("^(:[" .. symbol_char .. "]+)")) or attempt_match("number", "^([%+%-]?%d+[xX]?%d*%.?%d?)") or attempt_match("nil", ("^(nil)[^" .. symbol_char .. "]")) or attempt_match("boolean", ("^(true)[^" .. symbol_char .. "]")) or attempt_match("boolean", ("^(false)[^" .. symbol_char .. "]")) or attempt_match("symbol", ("^([" .. symbol_char .. "]+)")) or attempt_match("bracket", "^([%(%)%[%]{}])") or increment_current_index()) end
- end
- return yield_buffered_nonmatching()
-end
-local function with_symbol_subkind(syntax, _4_)
- local _arg_5_ = _4_
- local token = _arg_5_
- local kind = _arg_5_["kind"]
- local value = _arg_5_["value"]
- if ("symbol" == kind) then
- local _6_ = syntax[value]
- if ((_G.type(_6_) == "table") and ((_6_)["special?"] == true)) then
- token.subkind = "special-symbol"
- elseif ((_G.type(_6_) == "table") and ((_6_)["macro?"] == true)) then
- token.subkind = "macro-symbol"
- elseif ((_G.type(_6_) == "table") and ((_6_)["global?"] == true)) then
- token.subkind = "global-symbol"
- else
- token.subkind = nil
- end
- else
- end
- return token
-end
-local function token__3ehtml(_9_)
- local _arg_10_ = _9_
- local kind = _arg_10_["kind"]
- local subkind = _arg_10_["subkind"]
- local value = _arg_10_["value"]
- local class = ((kind or "nonmatching") .. " " .. (subkind or ""))
- local escaped_value = string.gsub(string.gsub(value, "&", "&"), "<", "<")
- return ("<span class=\"" .. class .. "\">" .. escaped_value .. "</span>")
-end
-local function for_html(syntax, code)
- local tokens
- do
- local tbl_17_auto = {}
- local i_18_auto = #tbl_17_auto
- local function _11_()
- return scan((code .. "\n"))
- end
- for token in coroutine.wrap(_11_) do
- local val_19_auto = token__3ehtml(with_symbol_subkind(syntax, token))
- if (nil ~= val_19_auto) then
- i_18_auto = (i_18_auto + 1)
- do end (tbl_17_auto)[i_18_auto] = val_19_auto
- else
- end
- end
- tokens = tbl_17_auto
- end
- return table.concat(tokens)
-end
-
-function highlight_fennel()
- fennel_highlighted.innerHTML = for_html(syntax, fennel_source.value)
-end
-
-function highlight_lua()
- -- TODO: Implement :-)
- lua_highlighted.innerHTML = lua_source.value
-end
-
--- Initial run
-highlight_fennel()
-highlight_lua()
-
-fennel_source.onscroll = function()
- fennel_highlighted.scrollTop = fennel_source.scrollTop
- fennel_highlighted.scrollLeft = fennel_source.scrollLeft
-end
-
-lua_source.onscroll = function()
- lua_highlighted.scrollTop = lua_source.scrollTop
- lua_highlighted.scrollLeft = lua_source.scrollLeft
-end
-
-fennel_source.oninput = function()
- highlight_fennel()
- fennel_source.onscroll()
-end
-
-lua_source.oninput = function()
- highlight_lua()
- lua_source.onscroll()
-end
-
-function update_fennel_source(new_value)
- fennel_source.value = new_value
- highlight_fennel()
-end
-
-function update_lua_source(new_value)
- lua_source.value = new_value
- highlight_lua()
-end
-
-local anti_msg = "Compiled Lua to Fennel.\n\n"..
- "Note that compiling Lua to Fennel can result in some" ..
- " strange-looking code when\nusing constructs that Fennel" ..
- " does not support natively, like early returns."
-
-local init_worker = function(auto_click)
- -- TODO: multiple Fennel versions?
- local worker = js.new(js.global.Worker, "/see-worker.js")
- local send = function(isFennel, code)
- -- we can't send tables to workers, so we have to encode everything in
- -- strings. use an initial space for Fennel and initial tab for Lua code.
- local prefix = isFennel and " " or "\t"
- worker:postMessage(prefix .. code)
- end
-
- worker.onmessage = function(_, e)
- out.innerHTML = e.data -- loaded message
- -- don't set up handlers until we've loaded
- compile_fennel.onclick = function() send(true, fennel_source.value) end
- compile_lua.onclick = function() send(false, lua_source.value) end
-
- worker.onmessage = function(_, event)
- -- because we can't send tables as events, we encode the type of the
- -- message in the last character of the string.
- if event.data:match(" $") then
- update_lua_source(event.data)
- status("Compiled Fennel to Lua.", true)
- elseif event.data:match("\t$") then
- update_fennel_source(event.data)
- status(anti_msg, true)
- else
- status(event.data, false)
- end
- end
- if auto_click and auto_click.onclick then auto_click.onclick() end
- end
-end
-
-local load_direct = function(auto_click)
- local antifennel = dofile("antifennel.lua")
- local fennel = require("fennel")
- compile_fennel.onclick = function()
- local ok, code = pcall(fennel.compileString, fennel_source.value)
- if ok then
- update_lua_source(code)
- status("Compiled Fennel to Lua.", true)
- else
- status(tostring(code), false)
- end
- end
-
- compile_lua.onclick = function()
- -- for Lua that doesn't parse, antifennel gives crummy error messages
- local ok, msg = load(lua_source.value)
- if not ok then return status("Lua: " .. msg, false) end
-
- local ok, code = pcall(antifennel, lua_source.value)
- if ok then
- update_fennel_source(code)
- status(anti_msg, true)
- else
- status(tostring(code), false)
- end
- end
-
- out.innerHTML = "Loaded Fennel " .. fennel.version .. " in " .. _VERSION
- if auto_click and auto_click.onclick then auto_click.onclick() end
-end
-
-local started = false
-
-local init = function(auto_click)
- if started then return end
- started = true
- out.innerHTML = "Loading..."
-
- if js.global.Worker then
- init_worker(auto_click)
- elseif js.global.setTimeout then
- js.global:setTimeout(function() load_direct(auto_click) end)
- else
- return load_direct(auto_click)
- end
-end
-
-compile_fennel.onclick = init
-compile_lua.onclick = init
-fennel_source.onfocus = init
-lua_source.onfocus = init
-
---- Sample snippets
-
-local fennel_samples = {["pong movement"]=
- ";; Read the keyboard, move player accordingly\
-(local dirs {:up [0 -1] :down [0 1]\
- :left [-1 0] :right [1 0]})\
-\
-(each [key delta (pairs dirs)]\
- (when (love.keyboard.isDown key)\
- (let [[dx dy] delta\
- [px py] player\
- x (+ px (* dx player.speed dt))\
- y (+ py (* dy player.speed dt))]\
- (world:move player x y))))",
- fibonacci="(fn fibonacci [n]\
- (if (< n 2)\
- n\
- (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))\
-\
-(print (fibonacci 10))",
- walk="(fn walk-tree [root f custom-iterator]\
- (fn walk [iterfn parent idx node]\
- (when (f idx node parent)\
- (each [k v (iterfn node)]\
- (walk iterfn node k v))))\
- (walk (or custom-iterator pairs) nil nil root)\
- root)"}
-
-local lua_samples = {["sample select"]=
- "local sample_lua = document:getElementById(\"samples\")\
-local lua_samples = {}\
-\
-for name, sample in pairs(lua_samples) do\
- local option = document:createElement(\"option\")\
- option.innerHTML = name\
- sample_lua:appendChild(option)\
-end\
-\
-function sample_lua.onchange(self, e)\
- init()\
- local code = lua_samples[self.value]\
- if code then lua_source.value = code end\
-end",
- antifennel=
- "local function uncamelize(name)\
- local function splicedash(pre, cap)\
- return pre .. \"-\" .. cap:lower()\
- end\
- return name:gsub(\"([a-z0-9])([A-Z])\", splicedash)\
-end\
-\
-local function mangle(name, field)\
- if not field and reservedFennel[name] then\
- name = \"___\" .. name .. \"___\"\
- end\
- return field and name or\
- uncamelize(name):gsub(\"([a-z0-9])_\", \"%1-\")\
-end\
-\
-local function compile(rdr, filename)\
- local ls = lex_setup(rdr, filename)\
- local ast_builder = lua_ast.New(mangle)\
- local ast_tree = parse(ast_builder, ls)\
- return letter(compiler(nil, ast_tree))\
-end",
- ["love.run"]="function love.run()\
- love.load()\
- while true do\
- love.event.pump()\
- local needs_refresh = false\
- for name, a,b,c,d,e,f in love.event.poll() do\
- if(type(love[name]) == \"function\") then\
- love[name](a,b,c,d,e,f)\
- needs_refresh = true\
- elseif(name == \"quit\") then\
- os.exit()\
- end\
- end\
- for _,c in pairs(internal.coroutines) do\
- local ok, val = coroutine.resume(c)\
- if(ok and val) then needs_refresh = true\
- elseif(not ok) then print(val) end\
- end\
- for i,c in lume.ripairs(internal.coroutines) do\
- if(coroutine.status(c) == \"dead\") then\
- table.remove(internal.coroutines, i)\
- end\
- end\
- if(needs_refresh) then refresh() end\
- love.timer.sleep(0.05)\
- end\
-end"}
-
-local init_samples = function(id, samples, update_source)
- local select = document:getElementById(id)
- for name, sample in pairs(samples) do
- local option = document:createElement("option")
- option.innerHTML = name
- select:appendChild(option)
- end
-
- select.onchange = function(self, e)
- init()
- local code = samples[self.value]
- if code then update_source(code) end
- end
-end
-
-init_samples("sample-fennel", fennel_samples, update_fennel_source)
-init_samples("sample-lua", lua_samples, update_lua_source)
-
-if js.global.URLSearchParams then
- local params = js.new(js.global.URLSearchParams, document.location.search)
- local fennel_param = params:get("fennel")
- local lua_param = params:get("lua")
-
- if tostring(fennel_param) ~= "null" then
- update_fennel_source(fennel_param)
- init(compile_fennel)
- elseif tostring(lua_param) ~= "null" then
- update_lua_source(lua_param)
- init(compile_lua)
- end
-end