├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── Tupfile ├── codemirror2 ├── lib │ ├── codemirror.css │ ├── codemirror.js │ ├── overlay.js │ └── runmode.js ├── mode │ ├── lua │ │ ├── index.html │ │ └── lua.js │ └── moonscript │ │ ├── index.html │ │ └── moonscript.js └── theme │ ├── moon.css │ └── moon.less ├── download.sh ├── examples ├── basic_class.moon ├── callbacks.moon ├── list_comprehensions.moon ├── scope.moon └── sorting.moon ├── fonts ├── range-mono-medium-webfont.eot ├── range-mono-medium-webfont.svg ├── range-mono-medium-webfont.ttf ├── range-mono-medium-webfont.woff ├── range-regular-webfont.eot ├── range-regular-webfont.svg ├── range-regular-webfont.ttf ├── range-regular-webfont.woff ├── range-semibold-webfont.eot ├── range-semibold-webfont.svg ├── range-semibold-webfont.ttf ├── range-semibold-webfont.woff └── stylesheet.css ├── highlight.coffee ├── img └── github-icon.svg ├── index.coffee ├── index.html ├── lib ├── react-dom.min.js └── react.min.js ├── moonscript.c ├── moonscript.js ├── moonscript.js.mem ├── old ├── .gitignore └── moonc.c ├── package.json ├── style.scss └── worker_suffix.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | *.tar.gz 2 | lua-*/ 3 | lpeg-*/ 4 | node_modules/ 5 | .tup##### TUP GITIGNORE ##### 6 | ##### Lines below automatically generated by Tup. 7 | ##### Do not edit. 8 | .tup 9 | /.gitignore 10 | /highlight.js 11 | /index.js 12 | /style.css 13 | /worker.js 14 | /worker_suffix.js 15 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "moonscript"] 2 | path = moonscript 3 | url = git@github.com:leafo/moonscript.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: deploy_targets deploy 2 | 3 | CC=/usr/lib/emscripten/emcc 4 | FLAGS=-Ilua-5.3.2/src/ -std=gnu99 -DLUA_COMPAT_5_2 -O2 5 | EMSCRIPTEN_FLAGS=-s EXPORTED_FUNCTIONS="['_compile_moonscript', '_run_moonscript']" -s ALLOW_MEMORY_GROWTH=1 # -s MODULARIZE=1 --closure 1 6 | 7 | FILES=moonscript.c \ 8 | lua-5.3.2/src/lapi.c \ 9 | lua-5.3.2/src/lauxlib.c \ 10 | lua-5.3.2/src/lbaselib.c \ 11 | lua-5.3.2/src/lbitlib.c \ 12 | lua-5.3.2/src/lcode.c \ 13 | lua-5.3.2/src/lcorolib.c \ 14 | lua-5.3.2/src/lctype.c \ 15 | lua-5.3.2/src/ldblib.c \ 16 | lua-5.3.2/src/ldebug.c \ 17 | lua-5.3.2/src/ldo.c \ 18 | lua-5.3.2/src/ldump.c \ 19 | lua-5.3.2/src/lfunc.c \ 20 | lua-5.3.2/src/lgc.c \ 21 | lua-5.3.2/src/linit.c \ 22 | lua-5.3.2/src/liolib.c \ 23 | lua-5.3.2/src/llex.c \ 24 | lua-5.3.2/src/lmathlib.c \ 25 | lua-5.3.2/src/lmem.c \ 26 | lua-5.3.2/src/loadlib.c \ 27 | lua-5.3.2/src/lobject.c \ 28 | lua-5.3.2/src/lopcodes.c \ 29 | lua-5.3.2/src/loslib.c \ 30 | lua-5.3.2/src/lparser.c \ 31 | lua-5.3.2/src/lstate.c \ 32 | lua-5.3.2/src/lstring.c \ 33 | lua-5.3.2/src/lstrlib.c \ 34 | lua-5.3.2/src/ltable.c \ 35 | lua-5.3.2/src/ltablib.c \ 36 | lua-5.3.2/src/ltm.c \ 37 | lua-5.3.2/src/lundump.c \ 38 | lua-5.3.2/src/lutf8lib.c \ 39 | lua-5.3.2/src/lvm.c \ 40 | lua-5.3.2/src/lzio.c \ 41 | lpeg-1.0.0/lpcap.c \ 42 | lpeg-1.0.0/lpcode.c \ 43 | lpeg-1.0.0/lpprint.c \ 44 | lpeg-1.0.0/lptree.c \ 45 | lpeg-1.0.0/lpvm.c 46 | 47 | moonscript.js: $(FILES) 48 | $(CC) $(FLAGS) $(EMSCRIPTEN_FLAGS) $+ -o $@ 49 | echo ";" >> $@ 50 | 51 | deploy_targets: 52 | @find -L . -type f | grep -P -v '^\./(node_modules|fonts|lua\-|lpeg\-|codemirror2|moonscript\/)' | grep -P '\.(js|mem|css|html|svg)$$' 53 | @find -L ./fonts -type f 54 | 55 | deploy: 56 | rsync -RvuzL $$(make -s deploy_targets) leaf@leafo.net:www/moonscript.org/compiler 57 | 58 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MoonScript for JavaScript 2 | 3 | This is a version of [MoonScript](http://moonscript.org) that has been compiled to 4 | JavaScript using [Emscripten](http://emscripten.org). 5 | 6 | ## About 7 | 8 | The Lua source code of MoonScript is concatenated into a single file which is 9 | converted to a header using `xxd`. This is included in a C file along with Lua and 10 | LPeg which are then compiled into LLVM bitcode. Finally the entire thing is 11 | linked and fed into Emscripten to create a JavaScript file. 12 | 13 | A simple HTML page creates the worker to provide an web interface for compiling 14 | and running MoonScript. 15 | 16 | Check it out at . 17 | 18 | -------------------------------------------------------------------------------- /Tupfile: -------------------------------------------------------------------------------- 1 | .gitignore 2 | 3 | !coffee = |> ^ coffee %o^ cat %f | coffee -c -s > %o |> 4 | !scss = |> ^ scss %o^ sassc -I scss/ < %f | postcss --use autoprefixer > %o |> 5 | !join = |> ^ join %o^ cat %f > %o |> 6 | 7 | : foreach *.scss |> !scss |> %B.css 8 | : foreach *.coffee |> !coffee |> %B.js 9 | : moonscript.js worker_suffix.js |> !join |> worker.js 10 | 11 | -------------------------------------------------------------------------------- /codemirror2/lib/codemirror.css: -------------------------------------------------------------------------------- 1 | .CodeMirror { 2 | line-height: 1em; 3 | font-family: monospace; 4 | } 5 | 6 | .CodeMirror-scroll { 7 | overflow: auto; 8 | height: 300px; 9 | /* This is needed to prevent an IE[67] bug where the scrolled content 10 | is visible outside of the scrolling box. */ 11 | position: relative; 12 | } 13 | 14 | .CodeMirror-gutter { 15 | position: absolute; left: 0; top: 0; 16 | z-index: 10; 17 | background-color: #f7f7f7; 18 | border-right: 1px solid #eee; 19 | min-width: 2em; 20 | height: 100%; 21 | } 22 | .CodeMirror-gutter-text { 23 | color: #aaa; 24 | text-align: right; 25 | padding: .4em .2em .4em .4em; 26 | } 27 | .CodeMirror-lines { 28 | padding: .4em; 29 | } 30 | 31 | .CodeMirror pre { 32 | -moz-border-radius: 0; 33 | -webkit-border-radius: 0; 34 | -o-border-radius: 0; 35 | border-radius: 0; 36 | border-width: 0; margin: 0; padding: 0; background: transparent; 37 | font-family: inherit; 38 | font-size: inherit; 39 | padding: 0; margin: 0; 40 | white-space: pre; 41 | word-wrap: normal; 42 | } 43 | 44 | .CodeMirror textarea { 45 | font-family: inherit !important; 46 | font-size: inherit !important; 47 | } 48 | 49 | .CodeMirror-cursor { 50 | z-index: 10; 51 | position: absolute; 52 | visibility: hidden; 53 | border-left: 1px solid black !important; 54 | } 55 | .CodeMirror-focused .CodeMirror-cursor { 56 | visibility: visible; 57 | } 58 | 59 | span.CodeMirror-selected { 60 | background: #ccc !important; 61 | color: HighlightText !important; 62 | } 63 | .CodeMirror-focused span.CodeMirror-selected { 64 | background: Highlight !important; 65 | } 66 | 67 | .CodeMirror-matchingbracket {color: #0f0 !important;} 68 | .CodeMirror-nonmatchingbracket {color: #f22 !important;} 69 | -------------------------------------------------------------------------------- /codemirror2/lib/overlay.js: -------------------------------------------------------------------------------- 1 | // Utility function that allows modes to be combined. The mode given 2 | // as the base argument takes care of most of the normal mode 3 | // functionality, but a second (typically simple) mode is used, which 4 | // can override the style of text. Both modes get to parse all of the 5 | // text, but when both assign a non-null style to a piece of code, the 6 | // overlay wins, unless the combine argument was true, in which case 7 | // the styles are combined. 8 | 9 | CodeMirror.overlayParser = function(base, overlay, combine) { 10 | return { 11 | startState: function() { 12 | return { 13 | base: CodeMirror.startState(base), 14 | overlay: CodeMirror.startState(overlay), 15 | basePos: 0, baseCur: null, 16 | overlayPos: 0, overlayCur: null 17 | }; 18 | }, 19 | copyState: function(state) { 20 | return { 21 | base: CodeMirror.copyState(base, state.base), 22 | overlay: CodeMirror.copyState(overlay, state.overlay), 23 | basePos: state.basePos, baseCur: null, 24 | overlayPos: state.overlayPos, overlayCur: null 25 | }; 26 | }, 27 | 28 | token: function(stream, state) { 29 | if (stream.start == state.basePos) { 30 | state.baseCur = base.token(stream, state.base); 31 | state.basePos = stream.pos; 32 | } 33 | if (stream.start == state.overlayPos) { 34 | stream.pos = stream.start; 35 | state.overlayCur = overlay.token(stream, state.overlay); 36 | state.overlayPos = stream.pos; 37 | } 38 | stream.pos = Math.min(state.basePos, state.overlayPos); 39 | if (stream.eol()) state.basePos = state.overlayPos = 0; 40 | 41 | if (state.overlayCur == null) return state.baseCur; 42 | if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur; 43 | else return state.overlayCur; 44 | }, 45 | 46 | indent: function(state, textAfter) { 47 | return base.indent(state.base, textAfter); 48 | }, 49 | electricChars: base.electricChars 50 | }; 51 | }; 52 | -------------------------------------------------------------------------------- /codemirror2/lib/runmode.js: -------------------------------------------------------------------------------- 1 | CodeMirror.runMode = function(string, modespec, callback) { 2 | var mode = CodeMirror.getMode({indentUnit: 2}, modespec); 3 | var isNode = callback.nodeType == 1; 4 | if (isNode) { 5 | var node = callback, accum = []; 6 | callback = function(string, style) { 7 | if (string == "\n") 8 | accum.push("
"); 9 | else if (style) 10 | accum.push("" + CodeMirror.htmlEscape(string) + ""); 11 | else 12 | accum.push(CodeMirror.htmlEscape(string)); 13 | } 14 | } 15 | var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode); 16 | for (var i = 0, e = lines.length; i < e; ++i) { 17 | if (i) callback("\n"); 18 | var stream = new CodeMirror.StringStream(lines[i]); 19 | while (!stream.eol()) { 20 | var style = mode.token(stream, state); 21 | callback(stream.current(), style); 22 | stream.start = stream.pos; 23 | } 24 | } 25 | if (isNode) 26 | node.innerHTML = accum.join(""); 27 | }; 28 | -------------------------------------------------------------------------------- /codemirror2/mode/lua/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CodeMirror 2: Lua mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

CodeMirror 2: Lua mode

14 |
55 | 62 | 63 |

Loosely based on Franciszek 64 | Wawrzak's CodeMirror 65 | 1 mode. One configuration parameter is 66 | supported, specials, to which you can provide an 67 | array of strings to have those identifiers highlighted with 68 | the lua-special style.

69 |

MIME types defined: text/x-lua.

70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /codemirror2/mode/lua/lua.js: -------------------------------------------------------------------------------- 1 | // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's 2 | // CodeMirror 1 mode. 3 | // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting 4 | 5 | CodeMirror.defineMode("lua", function(config, parserConfig) { 6 | var indentUnit = config.indentUnit; 7 | 8 | function prefixRE(words) { 9 | return new RegExp("^(?:" + words.join("|") + ")", "i"); 10 | } 11 | function wordRE(words) { 12 | return new RegExp("^(?:" + words.join("|") + ")$", "i"); 13 | } 14 | var specials = wordRE(parserConfig.specials || []); 15 | 16 | // long list of standard functions from lua manual 17 | var builtins = wordRE([ 18 | "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load", 19 | "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require", 20 | "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall", 21 | 22 | "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield", 23 | 24 | "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable", 25 | "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable", 26 | "debug.setupvalue","debug.traceback", 27 | 28 | "close","flush","lines","read","seek","setvbuf","write", 29 | 30 | "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin", 31 | "io.stdout","io.tmpfile","io.type","io.write", 32 | 33 | "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg", 34 | "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max", 35 | "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh", 36 | "math.sqrt","math.tan","math.tanh", 37 | 38 | "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale", 39 | "os.time","os.tmpname", 40 | 41 | "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload", 42 | "package.seeall", 43 | 44 | "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub", 45 | "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper", 46 | 47 | "table.concat","table.insert","table.maxn","table.remove","table.sort" 48 | ]); 49 | var keywords = wordRE(["and","break","elseif","false","nil","not","or","return", 50 | "true","function", "end", "if", "then", "else", "do", 51 | "while", "repeat", "until", "for", "in", "local" ]); 52 | 53 | var indentTokens = wordRE(["function", "if","repeat","for","while", "\\(", "{"]); 54 | var dedentTokens = wordRE(["end", "until", "\\)", "}"]); 55 | var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]); 56 | 57 | function readBracket(stream) { 58 | var level = 0; 59 | while (stream.eat("=")) ++level; 60 | stream.eat("["); 61 | return level; 62 | } 63 | 64 | function normal(stream, state) { 65 | var ch = stream.next(); 66 | if (ch == "-" && stream.eat("-")) { 67 | if (stream.eat("[")) 68 | return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state); 69 | stream.skipToEnd(); 70 | return "comment"; 71 | } 72 | if (ch == "\"" || ch == "'") 73 | return (state.cur = string(ch))(stream, state); 74 | if (ch == "[" && /[\[=]/.test(stream.peek())) 75 | return (state.cur = bracketed(readBracket(stream), "string"))(stream, state); 76 | if (/\d/.test(ch)) { 77 | stream.eatWhile(/[\w.%]/); 78 | return "number"; 79 | } 80 | if (/[\w_]/.test(ch)) { 81 | stream.eatWhile(/[\w\\\-_.]/); 82 | return "variable"; 83 | } 84 | return null; 85 | } 86 | 87 | function bracketed(level, style) { 88 | return function(stream, state) { 89 | var curlev = null, ch; 90 | while ((ch = stream.next()) != null) { 91 | if (curlev == null) {if (ch == "]") curlev = 0;} 92 | else if (ch == "=") ++curlev; 93 | else if (ch == "]" && curlev == level) { state.cur = normal; break; } 94 | else curlev = null; 95 | } 96 | return style; 97 | }; 98 | } 99 | 100 | function string(quote) { 101 | return function(stream, state) { 102 | var escaped = false, ch; 103 | while ((ch = stream.next()) != null) { 104 | if (ch == quote && !escaped) break; 105 | escaped = !escaped && ch == "\\"; 106 | } 107 | if (!escaped) state.cur = normal; 108 | return "string"; 109 | }; 110 | } 111 | 112 | return { 113 | startState: function(basecol) { 114 | return {basecol: basecol || 0, indentDepth: 0, cur: normal}; 115 | }, 116 | 117 | token: function(stream, state) { 118 | if (stream.eatSpace()) return null; 119 | var style = state.cur(stream, state); 120 | var word = stream.current(); 121 | if (style == "variable") { 122 | if (keywords.test(word)) style = "keyword"; 123 | else if (builtins.test(word)) style = "builtin"; 124 | else if (specials.test(word)) style = "variable-2"; 125 | } 126 | if ((style != "lua-comment") && (style != "lua-string")){ 127 | if (indentTokens.test(word)) ++state.indentDepth; 128 | else if (dedentTokens.test(word)) --state.indentDepth; 129 | } 130 | return style; 131 | }, 132 | 133 | indent: function(state, textAfter) { 134 | var closing = dedentPartial.test(textAfter); 135 | return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0)); 136 | } 137 | }; 138 | }); 139 | 140 | CodeMirror.defineMIME("text/x-lua", "lua"); 141 | -------------------------------------------------------------------------------- /codemirror2/mode/moonscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22 | 23 | 24 | 25 |
26 | 27 |
28 | 29 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /codemirror2/mode/moonscript/moonscript.js: -------------------------------------------------------------------------------- 1 | 2 | CodeMirror.defineMode('moonscript', function(conf) { 3 | 4 | function regex_escape(text) { 5 | return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 6 | } 7 | 8 | function words(words) { 9 | var escaped = []; 10 | for (var i = 0; i < words.length; i++) { 11 | escaped.push(regex_escape(words[i])); 12 | } 13 | return new RegExp("^(?:" + escaped.join("|") + ")$", "i"); 14 | } 15 | 16 | function set(items) { 17 | var set = {}; 18 | for (var i = 0; i < items.length; i++) { 19 | set[items[i]] = true; 20 | } 21 | return set; 22 | } 23 | 24 | var keywords = words([ 25 | "class", "extends", "if", "then", "super", "do", "with", 26 | "import", "export", "while", "elseif", "return", "for", 27 | "in", "from", "when", "using", "else", "and", "or", "not", 28 | "switch", "break" 29 | ]); 30 | 31 | var special = words([ 32 | "self", "nil", "true", "false" 33 | ]); 34 | 35 | // from lua.js 36 | var builtins = words([ 37 | "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load", 38 | "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require", 39 | "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall", 40 | 41 | "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield", 42 | 43 | "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable", 44 | "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable", 45 | "debug.setupvalue","debug.traceback", 46 | 47 | "close","flush","lines","read","seek","setvbuf","write", 48 | 49 | "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin", 50 | "io.stdout","io.tmpfile","io.type","io.write", 51 | 52 | "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg", 53 | "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max", 54 | "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh", 55 | "math.sqrt","math.tan","math.tanh", 56 | 57 | "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale", 58 | "os.time","os.tmpname", 59 | 60 | "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload", 61 | "package.seeall", 62 | 63 | "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub", 64 | "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper", 65 | 66 | "table.concat","table.insert","table.maxn","table.remove","table.sort" 67 | ]); 68 | 69 | var proper = /^[A-Z]/; 70 | var number = /^(?:0x[0-9a-f]+)|(?:[0-9]+(?:\.[0-9]*)?(?:e-?[0-9]+)?)/i; 71 | 72 | var symbols_a = set(['}', '{', '[', ']', '(', ')']); 73 | var symbols_b = set([ 74 | '!', '\\', '#', '<', '>', '=', '+', 75 | '*', '/', '^', ',', ':', '.' 76 | ]); 77 | 78 | function lua_string(stream) { 79 | if (stream.skipTo("]")) { 80 | stream.eat("]"); 81 | var rem = this.lua_string_len; 82 | while (stream.eat("=") && rem > 0) { 83 | rem--; 84 | } 85 | 86 | if (rem == 0 && stream.eat("]")) { 87 | delete this.lua_string_len; 88 | this.scanner = normal; 89 | return "string"; 90 | } 91 | } 92 | stream.skipToEnd(); 93 | return "string"; 94 | } 95 | 96 | function normal(stream) { 97 | var ch = stream.next(); 98 | 99 | if (ch == "-") { 100 | if (stream.eat(">")) return "fn_symbol"; 101 | if (stream.match(number)) return "number"; 102 | if (stream.eat("-")) { 103 | stream.skipToEnd(); 104 | return "comment" 105 | } 106 | } else if (ch.match(/[a-z]/i)) { 107 | stream.eatWhile(/[a-z_0-9]/i); 108 | var word = stream.current(); 109 | if (word.match(special)) return "atom"; 110 | if (word.match(keywords)) { 111 | return "keyword"; 112 | } else if (word.match(proper)) { 113 | return "atom"; 114 | } 115 | 116 | if (stream.peek() == ":") { 117 | return "key"; 118 | } 119 | 120 | // try for a builtin 121 | var got_more = false 122 | if (stream.eat(".")) { 123 | stream.eatWhile(/[A-Za-z]/); 124 | word = stream.current(); 125 | got_more = true; 126 | } 127 | 128 | if (word.match(builtins)) { 129 | return "builtin" 130 | } else if (got_more) { 131 | var match = word.match(/\.[^.]*$/); 132 | stream.backUp(match[0].length); 133 | } 134 | 135 | } else if (ch == "'" || ch == '"') { 136 | var quote = regex_escape(ch); 137 | var str = new RegExp('^(?:\\\\'+quote+'|[^'+quote+'])*'+quote); 138 | if (!stream.match(str)) stream.skipToEnd(); 139 | return "string" 140 | } else if (ch.match(number)) { 141 | stream.backUp(1); 142 | stream.match(number); 143 | return "number"; 144 | } else if (ch == "=") { 145 | if (stream.eat(">")) return "fn_symbol"; 146 | } else if (ch == "[") { 147 | stream.eatWhile("="); 148 | this.lua_string_len = stream.current().length - 1; 149 | if (stream.eat("[")) { 150 | this.scanner = lua_string; 151 | return this.scanner(stream); 152 | } 153 | } else if (ch == "@") { 154 | stream.eatWhile(/[\w0-9_-]/); 155 | return "atom"; 156 | } 157 | 158 | if (symbols_a[ch]) return "fn_symbol"; 159 | if (symbols_b[ch]) return "symbol"; 160 | } 161 | 162 | return { 163 | startState: function(basecol) { 164 | return { scanner: normal } 165 | }, 166 | 167 | token: function(stream, state) { 168 | if (stream.eatSpace()) return null; 169 | return state.scanner(stream); 170 | } 171 | } 172 | }); 173 | -------------------------------------------------------------------------------- /codemirror2/theme/moon.css: -------------------------------------------------------------------------------- 1 | .cm-s-moon { 2 | background: #2E2E2E; 3 | color: white; 4 | } 5 | .cm-s-moon span.CodeMirror-selected { 6 | background: #a8f !important; 7 | } 8 | .cm-s-moon .CodeMirror-gutter { 9 | background: #464646; 10 | border-right: 1px solid #797979; 11 | } 12 | .cm-s-moon .CodeMirror-gutter-text { 13 | color: #B3B3B3; 14 | color: #585858; 15 | } 16 | .cm-s-moon .CodeMirror-cursor { 17 | border-left: 10px solid white !important; 18 | } 19 | .cm-s-moon .cm-keyword { 20 | color: #cb98ff; 21 | font-weight: bold; 22 | } 23 | .cm-s-moon .cm-atom { 24 | color: #98d9ff; 25 | } 26 | .cm-s-moon .cm-string { 27 | color: #ffe898; 28 | } 29 | .cm-s-moon .cm-comment { 30 | color: #929292; 31 | } 32 | .cm-s-moon .cm-builtin { 33 | color: #FF9200; 34 | } 35 | .cm-s-moon .cm-fn_symbol { 36 | color: #9fff98; 37 | } 38 | .cm-s-moon .cm-symbol, .cm-s-moon .cm-key { 39 | color: #ff9898; 40 | } 41 | .cm-s-moon .cm-number { 42 | color: #9495FF; 43 | } 44 | .l_string { 45 | color: #ffe898; 46 | } 47 | .l_symbol { 48 | color: #ff9898; 49 | } 50 | .l_keyword { 51 | color: #cb98ff; 52 | font-weight: bold; 53 | } 54 | .l_proper, .l_self_var { 55 | color: #98d9ff; 56 | } 57 | .l_fn_symbol { 58 | color: #9fff98; 59 | } 60 | -------------------------------------------------------------------------------- /codemirror2/theme/moon.less: -------------------------------------------------------------------------------- 1 | 2 | 3 | .cm-s-moon { 4 | background: #2E2E2E; 5 | color: white; 6 | 7 | 8 | span.CodeMirror-selected { 9 | background: #a8f !important; 10 | } 11 | 12 | .CodeMirror-gutter { 13 | background: #464646; 14 | border-right: 1px solid #797979; 15 | } 16 | 17 | .CodeMirror-gutter-text { 18 | color: #B3B3B3; 19 | color: #585858; 20 | } 21 | 22 | .CodeMirror-cursor { 23 | border-left: 10px solid white !important; 24 | } 25 | 26 | .cm-keyword { 27 | color: #cb98ff; font-weight: bold; 28 | } 29 | 30 | .cm-atom { 31 | color: #98d9ff; 32 | } 33 | 34 | 35 | .cm-string { 36 | color: #ffe898; 37 | } 38 | 39 | .cm-comment { 40 | color: #929292; 41 | } 42 | 43 | 44 | .cm-builtin { 45 | color: #FF9200; 46 | } 47 | 48 | .cm-fn_symbol { 49 | color: #9fff98; 50 | } 51 | 52 | .cm-symbol, .cm-key { 53 | color: #ff9898; 54 | } 55 | 56 | .cm-number { 57 | color: #9495FF; 58 | } 59 | 60 | } 61 | 62 | 63 | .l_string { color: #ffe898; } 64 | .l_symbol { color: #ff9898; } 65 | .l_keyword { color: #cb98ff; font-weight: bold; } 66 | .l_proper, .l_self_var { color: #98d9ff; } 67 | .l_fn_symbol { color: #9fff98; } 68 | 69 | -------------------------------------------------------------------------------- /download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -O http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.0.tar.gz 4 | curl -O http://www.lua.org/ftp/lua-5.3.2.tar.gz 5 | 6 | tar xzf lpeg-1.0.0.tar.gz 7 | tar xzf lua-5.3.2.tar.gz 8 | -------------------------------------------------------------------------------- /examples/basic_class.moon: -------------------------------------------------------------------------------- 1 | class Inventory 2 | new: => 3 | @items = {} 4 | 5 | add_item: (name, amount=1) => 6 | if @items[name] 7 | @items[name] += amount 8 | else 9 | @items[name] = amount 10 | 11 | show: => 12 | for item, count in pairs @items 13 | print item, count 14 | 15 | inv = with Inventory! 16 | \add_item "t-shirt" 17 | \add_item "pants" 18 | \add_item "pants" 19 | \add_item "boots", 4 20 | 21 | 22 | print "I have:" 23 | inv\show! 24 | -------------------------------------------------------------------------------- /examples/callbacks.moon: -------------------------------------------------------------------------------- 1 | -- repeat function n times 2 | rep = (n, fn)-> 3 | for i=1,n do fn! 4 | 5 | my_obj = { 6 | value: 100 7 | show: => 8 | print "My value is: " , @value 9 | @value += 1 10 | } 11 | 12 | my_obj\show! 13 | 14 | print "calling bound function:" 15 | bound = my_obj\show 16 | rep 5, bound 17 | 18 | -------------------------------------------------------------------------------- /examples/list_comprehensions.moon: -------------------------------------------------------------------------------- 1 | format = (list) -> 2 | if type(list) == "table" 3 | "{" .. table.concat([format item for item in *list], ", ") .. "}" 4 | else 5 | list 6 | 7 | -- double list of items 8 | items = {1,2,3,4,5} 9 | doubled = [i*2 for i in *items] 10 | 11 | print "doubled:", format doubled 12 | 13 | -- find points inside of the unit circle 14 | 15 | length = (x,y) -> math.sqrt x^2 + y^2 16 | 17 | pts = for i=0.5, 1.0, 0.2 do i 18 | inside = [{x,y} for x in *pts for y in *pts when length(x,y) <= 1.0] 19 | 20 | print "pts in circle: ", format inside 21 | 22 | -------------------------------------------------------------------------------- /examples/scope.moon: -------------------------------------------------------------------------------- 1 | 2 | import concat from table 3 | print concat {1,2,3,5,}, ", " 4 | 5 | tmp_val = 1000 6 | 7 | func_1 = (a using nil) -> 8 | tmp_val = 100 + a 9 | print "func_1:", tmp_val 10 | 11 | func_2 = (a using tmp_val) -> 12 | tmp_val = 100 + a 13 | print "func_2:", tmp_val 14 | 15 | 16 | func_1 99 -- doesn't mutate upper tmp_val 17 | print "tmp_val:", tmp_val 18 | 19 | func_2 99 20 | print "tmp_val:", tmp_val 21 | 22 | -------------------------------------------------------------------------------- /examples/sorting.moon: -------------------------------------------------------------------------------- 1 | format = (list) -> 2 | if type(list) == "table" 3 | "{" .. table.concat([format item for item in *list], ", ") .. "}" 4 | else 5 | list 6 | 7 | -- a (slow) quick sort using slices and comprehensions 8 | items = {4, 5, 2, 1, 3, 8, 9, 0} 9 | 10 | -- append array tables 11 | concat = (...) -> 12 | out = {} 13 | for t in *{...} 14 | table.insert out, i for i in *t 15 | out 16 | 17 | quicksort = (items) -> 18 | return {} if #items == 0 19 | pivot = items[1] 20 | rest = [i for i in *items[2:]] 21 | concat quicksort([i for i in *rest when i < pivot ]), 22 | {pivot}, 23 | quicksort([i for i in *rest when i >= pivot]) 24 | 25 | print format quicksort items 26 | 27 | -------------------------------------------------------------------------------- /fonts/range-mono-medium-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-mono-medium-webfont.eot -------------------------------------------------------------------------------- /fonts/range-mono-medium-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-mono-medium-webfont.ttf -------------------------------------------------------------------------------- /fonts/range-mono-medium-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-mono-medium-webfont.woff -------------------------------------------------------------------------------- /fonts/range-regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-regular-webfont.eot -------------------------------------------------------------------------------- /fonts/range-regular-webfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /fonts/range-regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-regular-webfont.ttf -------------------------------------------------------------------------------- /fonts/range-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-regular-webfont.woff -------------------------------------------------------------------------------- /fonts/range-semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-semibold-webfont.eot -------------------------------------------------------------------------------- /fonts/range-semibold-webfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /fonts/range-semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-semibold-webfont.ttf -------------------------------------------------------------------------------- /fonts/range-semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/fonts/range-semibold-webfont.woff -------------------------------------------------------------------------------- /fonts/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Generated by Font Squirrel (http://www.fontsquirrel.com) on September 4, 2014 */ 2 | 3 | 4 | 5 | @font-face { 6 | font-family: 'range_monomedium'; 7 | src: url('range-mono-medium-webfont.eot'); 8 | src: url('range-mono-medium-webfont.eot?#iefix') format('embedded-opentype'), 9 | url('range-mono-medium-webfont.woff') format('woff'), 10 | url('range-mono-medium-webfont.ttf') format('truetype'), 11 | url('range-mono-medium-webfont.svg#range_monomedium') format('svg'); 12 | font-weight: normal; 13 | font-style: normal; 14 | 15 | } 16 | 17 | 18 | 19 | 20 | @font-face { 21 | font-family: 'rangeregular'; 22 | src: url('range-regular-webfont.eot'); 23 | src: url('range-regular-webfont.eot?#iefix') format('embedded-opentype'), 24 | url('range-regular-webfont.woff') format('woff'), 25 | url('range-regular-webfont.ttf') format('truetype'), 26 | url('range-regular-webfont.svg#rangeregular') format('svg'); 27 | font-weight: normal; 28 | font-style: normal; 29 | 30 | } 31 | 32 | 33 | 34 | 35 | @font-face { 36 | font-family: 'rangesemibold'; 37 | src: url('range-semibold-webfont.eot'); 38 | src: url('range-semibold-webfont.eot?#iefix') format('embedded-opentype'), 39 | url('range-semibold-webfont.woff') format('woff'), 40 | url('range-semibold-webfont.ttf') format('truetype'), 41 | url('range-semibold-webfont.svg#rangesemibold') format('svg'); 42 | font-weight: normal; 43 | font-style: normal; 44 | 45 | } -------------------------------------------------------------------------------- /highlight.coffee: -------------------------------------------------------------------------------- 1 | is_alpha = (str) -> 2 | str.match /^[a-zA-Z_]+$/ 3 | 4 | wrap_word = (str) -> 5 | if is_alpha str 6 | "\\b#{str}\\b" 7 | else 8 | str 9 | 10 | unescape_html = (text) -> 11 | node = document.createElement "div" 12 | node.innerHTML = text 13 | if node.childNodes.length > 0 14 | node.childNodes[0].nodeValue 15 | else 16 | "" 17 | 18 | escape_html = (text) -> 19 | text.replace(//g, ">") 20 | 21 | class Highlighter 22 | attr_name: "class" 23 | constructor: -> 24 | @match_name_table = [] 25 | 26 | literal_matches = [] 27 | pattern_matches = [] 28 | for name, patterns of @matches 29 | patterns = [patterns] if patterns not instanceof Array 30 | for p in patterns 31 | if p instanceof RegExp 32 | pattern_matches.push [name, p.source] 33 | else 34 | literal_matches.push [name, @escape p] 35 | 36 | comp = (a,b) -> b[1].length - a[1].length 37 | literal_matches.sort comp 38 | pattern_matches.sort comp 39 | 40 | matches = literal_matches.concat pattern_matches 41 | matches = for i in [0...matches.length] 42 | [name, pattern] = matches[i] 43 | @match_name_table.push name 44 | "(" + wrap_word(pattern) + ")" 45 | 46 | @patt = matches.join("|") 47 | 48 | @r = new RegExp @patt, "g" 49 | @replace_all() 50 | 51 | replace_all: -> 52 | cls_name = "." + @name + "-code" 53 | nodes = document.querySelectorAll cls_name 54 | for node in nodes 55 | node.innerHTML = @format_text unescape_html node.innerHTML 56 | 57 | format_text: (text) -> 58 | text.replace @r, (match, params...) => 59 | i = 0 60 | while not params[i] and i < params.length 61 | i++ 62 | 63 | name = @match_name_table[i] 64 | @style match, @get_style name, match 65 | 66 | get_style: (name, value) -> 67 | fn = @theme?[name] or "l_#{name}" 68 | 69 | if typeof fn == "function" 70 | fn value 71 | else 72 | fn 73 | 74 | style: (text, style) -> 75 | text = escape_html text 76 | "#{text}" 77 | 78 | escape: (text) -> # pattern escape 79 | text.replace /[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&" 80 | 81 | builtins = [ 82 | "table.insert", "assert", "print" 83 | "ipairs", "pairs", "require", "module" 84 | "package.seeall" 85 | ] 86 | 87 | class LuaHighlighter extends Highlighter 88 | name: "lua" 89 | matches: 90 | fn_symbol: ["function"] 91 | keyword: [ 92 | "for", "end", "local", "if", "then", "return", "do" 93 | "and", "or", "else", "not", "while", "elseif" 94 | "break" 95 | ] 96 | special: ["nil", "true", "false"] 97 | symbol: ['=', '.', '{', '}', ':'] 98 | builtins: builtins 99 | atom: /[_A-Za-z][_A-Za-z0-9]*/ 100 | number: /-?\d+/ 101 | string: [/"[^"]*"/, /\[\[.*?]]/] 102 | comment: /--[^\n]*(?:\n|$)/ 103 | 104 | class MoonHighlighter extends Highlighter 105 | name: "moon" 106 | matches: 107 | keyword: [ 108 | "class", "extends", "if", "then", "super" 109 | "do", "with", "import", "export", "while" 110 | "elseif", "return", "for", "in", "from", "when" 111 | "using", "else", "and", "or", "not", "switch" 112 | "break", "continue" 113 | ] 114 | special: ["nil", "true", "false"] 115 | builtins: builtins 116 | self: ["self"] 117 | symbol: [ 118 | '!', '\\', '=', '+=', '-=' 119 | '...', '*', '>', '<', '#' 120 | ] 121 | bold_symbol: [':', '.'] 122 | fn_symbol: ['->', '=>', '}', '{', '[', ']'] 123 | self_var: /@[a-zA-Z_][a-zA-Z_0-9]*/ 124 | table_key: /[_A-Za-z][a-zA-Z_0-9]*(?=:)/ 125 | proper: /[A-Z][a-zA-Z_0-9]*/ 126 | atom: /[_A-Za-z]\w*/ 127 | number: /-?\d+/ 128 | string: [/"[^"]*"/, /\[\[.*?]]/] 129 | comment: /--[^\n]*(?:\n|$)/ 130 | 131 | window.LuaHighlighter = LuaHighlighter 132 | window.MoonHighlighter = MoonHighlighter 133 | -------------------------------------------------------------------------------- /img/github-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | 54 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /index.coffee: -------------------------------------------------------------------------------- 1 | 2 | window.MoonScript ||= {} 3 | 4 | { div, span, a, p, ol, ul, li, strong, em, img, 5 | form, label, input, textarea, button, 6 | h1, h2, h3, h4, h5, h6, pre, code } = React.DOM 7 | 8 | window.R = (name, data, p=R, prefix="") -> 9 | data.displayName = "R.#{prefix}#{name}" 10 | cl = React.createClass(data) 11 | p[name] = React.createFactory(cl) 12 | p[name]._class = cl 13 | 14 | R "MoonScriptCompiler", { 15 | getInitialState: -> 16 | @highlighter = new LuaHighlighter() 17 | 18 | { 19 | code_input: "" 20 | last_output: "" 21 | } 22 | 23 | componentDidMount: -> 24 | @setState initial_loading: true 25 | 26 | MoonScript.get_version().then (version) => 27 | @setState { 28 | initial_loading: false 29 | version: version 30 | } 31 | 32 | @try_compile() 33 | 34 | do_execute: -> 35 | @setState { 36 | input_timeout: null 37 | loading: true 38 | executing: true 39 | } 40 | 41 | to_execute = @state.code_input 42 | MoonScript.execute(to_execute).then (res) => 43 | return unless to_execute == @state.code_input 44 | 45 | @setState { 46 | last_output: res 47 | loading: false 48 | executing: false 49 | } 50 | 51 | 52 | do_compile: -> 53 | @setState { 54 | input_timeout: null 55 | loading: true 56 | } 57 | 58 | to_compile = @state.code_input 59 | MoonScript.compile(to_compile).then (res) => 60 | return unless to_compile == @state.code_input 61 | 62 | @setState { 63 | last_output: res 64 | loading: false 65 | } 66 | 67 | try_compile: -> 68 | return if @state.initial_loading 69 | return if @state.executing 70 | 71 | if @state.input_timeout 72 | clearTimeout @state.input_timeout 73 | 74 | @setState { 75 | input_timeout: setTimeout @do_compile, 50 76 | } 77 | 78 | render: -> 79 | div children: [ 80 | div className: "header", children: [ 81 | "MoonScript online compiler" 82 | " " 83 | a className: "return_link", href: "http://moonscript.org", "← Return to MoonScript.org" 84 | 85 | div className: "header_right", children: [ 86 | if @state.initial_loading 87 | span className: "status_flag loading", "Loading..." 88 | else 89 | a href: "https://github.com/leafo/moonscript/blob/master/CHANGELOG.md", className: "status_flag ready", "#{@state.version}" 90 | 91 | a className: "github_link", href: "https://github.com/leafo/moonscript-javascript", 92 | img width: "30", height: "30", src: "img/github-icon.svg" 93 | ] 94 | ] 95 | 96 | div className: "code_column", children: [ 97 | textarea { 98 | value: @state.code_input 99 | className: "code_input" 100 | placeholder: "Write MoonScript here..." 101 | onChange: (e) => 102 | @setState code_input: e.target.value 103 | @try_compile() 104 | } 105 | div className: "button_toolbar", children: [ 106 | button { 107 | className: "button" 108 | onClick: @do_execute 109 | }, "Execute" 110 | ] 111 | ] 112 | 113 | div className: "output_column", children: [ 114 | div className: "output_status", children: [ 115 | if @state.initial_loading 116 | "Warming up compiler..." 117 | else if @state.executing 118 | "Executing..." 119 | else if @state.loading 120 | "Compiling..." 121 | else 122 | "Ready" 123 | ] 124 | 125 | pre { 126 | className: "value code_output" 127 | key: "code_output" 128 | dangerouslySetInnerHTML: { 129 | __html: @highlighter.format_text @state.last_output 130 | } 131 | } 132 | ] 133 | 134 | ] 135 | } 136 | 137 | class MoonWorker 138 | id: 0 139 | 140 | constructor: -> 141 | @worker = new Worker "worker.js" 142 | @listeners = {} 143 | @worker.onmessage = (e) => 144 | [return_id, result] = e.data 145 | if @listeners[return_id]? 146 | fn = @listeners[return_id] 147 | fn result 148 | 149 | send: (args...) -> 150 | send_id = @id 151 | @id += 1 152 | 153 | @worker.postMessage [send_id, args...] 154 | new Promise (resolve) => 155 | @listen send_id, resolve 156 | 157 | listen: (id, fn) -> 158 | @listeners[id] = fn 159 | 160 | MoonScript.get_worker = -> 161 | MoonScript.worker ||= new MoonWorker 162 | 163 | blank_promise = new Promise (r) -> r "" 164 | 165 | MoonScript.compile = (code) -> 166 | return blank_promise if code == "" 167 | 168 | worker = MoonScript.get_worker() 169 | worker.send "compile", code 170 | 171 | MoonScript.execute = (code) -> 172 | return blank_promise if code == "" 173 | worker = MoonScript.get_worker() 174 | worker.send "execute", code 175 | 176 | MoonScript.get_version = -> 177 | MoonScript.execute "print require('moonscript.version').version" 178 | 179 | MoonScript.render = -> 180 | body = document.querySelector("#body") 181 | component = R.MoonScriptCompiler {} 182 | ReactDOM.render(component, body) 183 | 184 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MoonScript Online Compiler 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 | 33 |
34 | 35 | 36 | 39 | 40 | -------------------------------------------------------------------------------- /lib/react-dom.min.js: -------------------------------------------------------------------------------- 1 | ../node_modules/react-dom/dist/react-dom.min.js -------------------------------------------------------------------------------- /lib/react.min.js: -------------------------------------------------------------------------------- 1 | ../node_modules/react/dist/react.min.js -------------------------------------------------------------------------------- /moonscript.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "moonscript/moonscript.h" 10 | 11 | #define CODE(...) #__VA_ARGS__ 12 | 13 | int luaopen_lpeg (lua_State *L); 14 | 15 | lua_State* L; 16 | int default_stack_size; 17 | 18 | const char* moonscript_to_lua_src = CODE( 19 | return require('moonscript.base').to_lua(...) 20 | ); 21 | 22 | const char* execute_moonscript_src = CODE( 23 | local fn, err = require('moonscript.base').loadstring(...) 24 | 25 | if not fn then 26 | return err 27 | end 28 | return fn() 29 | ); 30 | 31 | // put whatever is on top of stack into package.loaded under name something is 32 | // already there 33 | void setloaded(lua_State* l, char* name) { 34 | int top = lua_gettop(l); 35 | lua_getglobal(l, "package"); 36 | lua_getfield(l, -1, "loaded"); 37 | lua_getfield(l, -1, name); 38 | if (lua_isnil(l, -1)) { 39 | lua_pop(l, 1); 40 | lua_pushvalue(l, top); 41 | lua_setfield(l, -2, name); 42 | } 43 | 44 | lua_settop(l, top); 45 | } 46 | 47 | void setup_lua() { 48 | if (L) { 49 | return; 50 | } 51 | 52 | L = luaL_newstate(); 53 | luaL_openlibs(L); 54 | 55 | luaopen_lpeg(L); 56 | setloaded(L, "lpeg"); 57 | 58 | if (luaL_loadbuffer(L, (const char *)moonscript_lua, moonscript_lua_len, "moonscript.lua") != LUA_OK) { 59 | fprintf(stderr, "Failed to load moonscript.lua\n"); 60 | return; 61 | } 62 | lua_call(L, 0, 0); 63 | 64 | default_stack_size = lua_gettop(L); 65 | } 66 | 67 | 68 | const char* run_moonscript(const char* input) { 69 | setup_lua(); 70 | lua_pop(L, lua_gettop(L) - default_stack_size); 71 | 72 | if (luaL_loadbuffer(L, execute_moonscript_src, strlen(execute_moonscript_src), "execute_moonscript") != LUA_OK) { 73 | return "Failed to load code compiler"; 74 | } 75 | 76 | lua_pushstring(L, input); 77 | int res = lua_pcall(L, 1, 1, 0); 78 | 79 | // both return value and error is returned 80 | return lua_tostring(L, -1); 81 | } 82 | 83 | const char* compile_moonscript(const char* input) { 84 | setup_lua(); 85 | lua_pop(L, lua_gettop(L) - default_stack_size); 86 | 87 | if (luaL_loadbuffer(L, moonscript_to_lua_src, strlen(moonscript_to_lua_src), "moonscript_to_lua") != LUA_OK) { 88 | return "Failed to load code compiler"; 89 | } 90 | 91 | lua_pushstring(L, input); 92 | int res = lua_pcall(L, 1, 2, 0); 93 | 94 | // this will return either: 95 | // 1. compiled code 96 | // 2. exception error 97 | // 3. compile error 98 | // 99 | // We currently make no destinction between compiled code an an error :( 100 | 101 | if (lua_isstring(L, -1)) { 102 | return lua_tostring(L, -1); 103 | } else { 104 | return lua_tostring(L, -2); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /moonscript.js.mem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leafo/moonscript-javascript/b3a272d4d5eb49ce6e8339ba7bfe1530e7ba8681/moonscript.js.mem -------------------------------------------------------------------------------- /old/.gitignore: -------------------------------------------------------------------------------- 1 | *.bc 2 | *.js 3 | moonscript 4 | -------------------------------------------------------------------------------- /old/moonc.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lualib.h" 3 | #include "lauxlib.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "moonscript.h" 10 | 11 | extern int luaopen_lpeg(lua_State *l); 12 | 13 | lua_State *l; 14 | 15 | char *last_error = 0; 16 | 17 | int _format_error(lua_State *l) { 18 | int msg = lua_gettop(l); 19 | 20 | lua_getfield(l, LUA_GLOBALSINDEX, "debug"); 21 | lua_getfield(l, -1, "traceback"); 22 | 23 | lua_pushvalue(l, msg); 24 | lua_pushinteger(l, 2); 25 | 26 | lua_call(l, 2, 1); 27 | 28 | return 1; 29 | } 30 | 31 | int run_lua(char *code) { 32 | lua_pushcfunction(l, _format_error); 33 | luaL_loadstring(l, code); 34 | if (lua_pcall(l, 0, 0, -2)) { 35 | // store the error 36 | if (last_error) { 37 | free(last_error); 38 | last_error = 0; 39 | } 40 | 41 | size_t str_len; 42 | const char *str = luaL_checklstring(l, -1, &str_len); 43 | last_error = malloc(str_len + 1); 44 | memcpy(last_error, str, str_len); 45 | last_error[str_len] = 0; 46 | 47 | return 1; 48 | } 49 | lua_pop(l, 1); // remove handler 50 | return 0; 51 | } 52 | 53 | void write_error() { 54 | if (last_error) { 55 | printf("%s\n", last_error); 56 | free(last_error); 57 | last_error = 0; 58 | } 59 | } 60 | 61 | int main(int argc, char **argv) { 62 | printf("%d arguments:\n", argc); 63 | for (int i = 0; i < argc; i++) { 64 | printf(" * %s\n", argv[i]); 65 | } 66 | 67 | l = luaL_newstate(); 68 | luaL_openlibs(l); 69 | 70 | luaopen_lpeg(l); 71 | 72 | if (!luaL_loadbuffer(l, (const char *)moonscript_lua, moonscript_lua_len, "moonscript.lua") == 0) { 73 | fprintf(stderr, "Failed to load moonscript.lua\n"); 74 | return 1; 75 | } 76 | lua_call(l, 0, 0); 77 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "moonscript-javascript", 3 | "version": "1.0.0", 4 | "description": "This is a version of [MoonScript](http://moonscript.org) that has been compiled to JavaScript using [Emscripten](http://emscripten.org).", 5 | "main": "moonscript.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "dependencies": { 10 | "classnames": "^2.2.1", 11 | "react": "^0.14.3", 12 | "react-dom": "^0.14.3" 13 | }, 14 | "devDependencies": {}, 15 | "scripts": { 16 | "test": "echo \"Error: no test specified\" && exit 1" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/leafo/moonscript-javascript.git" 21 | }, 22 | "author": "", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/leafo/moonscript-javascript/issues" 26 | }, 27 | "homepage": "https://github.com/leafo/moonscript-javascript#readme" 28 | } 29 | -------------------------------------------------------------------------------- /style.scss: -------------------------------------------------------------------------------- 1 | $link_color: #f05a7f; 2 | 3 | body { 4 | font-family: rangeregular; 5 | padding: 0; 6 | margin: 0; 7 | background: #F0F0F0; 8 | color: #222; 9 | } 10 | 11 | a { 12 | color: $link_color; 13 | text-decoration: none; 14 | } 15 | 16 | .header { 17 | height: 50px; 18 | background: rgba(black, 0.8); 19 | color: white; 20 | line-height: 50px; 21 | padding: 0 20px; 22 | position: fixed; 23 | top: 0; 24 | left: 0; 25 | right: 0; 26 | z-index: 2; 27 | 28 | .return_link { 29 | color: #888; 30 | margin-left: 15px; 31 | font-size: 14px; 32 | 33 | &:hover { 34 | color: lighten(#888, 10%); 35 | } 36 | } 37 | 38 | .header_right { 39 | position: absolute; 40 | top: 0; 41 | right: 20px; 42 | line-height: 50px; 43 | 44 | .github_link { 45 | display: inline-block; 46 | vertical-align: top; 47 | margin-top: 8px; 48 | margin-left: 20px; 49 | width: 30px; 50 | height: 30px; 51 | 52 | img { 53 | border: 0; 54 | display: block; 55 | width: 30px; 56 | height: 30px; 57 | } 58 | } 59 | 60 | } 61 | 62 | .status_flag { 63 | transition: 0.4s ease background; 64 | padding: 8px 10px; 65 | line-height: normal; 66 | display: inline-block; 67 | border-radius: 8px; 68 | color: white; 69 | 70 | &.loading { 71 | background: #f277a1; 72 | } 73 | 74 | &.ready { 75 | background: #8EB17D; 76 | } 77 | } 78 | } 79 | 80 | .output_column { 81 | margin: 60px 20px 20px 50%; 82 | box-sizing: border-box; 83 | } 84 | 85 | .output_status { 86 | background: #DCDCDC; 87 | padding: 10px; 88 | } 89 | 90 | .code_output { 91 | font-size: 18px; 92 | color: #666; 93 | 94 | .l_builtins { 95 | color: #707A34; 96 | } 97 | 98 | .l_string { 99 | color: #A16D43; 100 | } 101 | 102 | .l_number { 103 | color: #893D8C; 104 | } 105 | 106 | .l_function { 107 | color: #8E4681; 108 | } 109 | 110 | .l_symbol { 111 | color: #B50C0C; 112 | } 113 | 114 | .l_proper { 115 | color: #30A0BD; 116 | } 117 | 118 | .l_keyword { 119 | color: #0CB56C; 120 | } 121 | 122 | .l_atom { 123 | color: #333; 124 | } 125 | } 126 | 127 | .code_column { 128 | position: fixed; 129 | top: 60px; 130 | bottom: 20px; 131 | width: calc(50% - 20px); 132 | left: 10px; 133 | display: flex; 134 | flex-direction: column; 135 | } 136 | 137 | .code_input { 138 | font-family: range_monomedium; 139 | box-sizing: border-box; 140 | font-size: 18px; 141 | border: 1px solid #dadada; 142 | border-radius: 2px; 143 | padding: 10px; 144 | color: #444; 145 | width: 100%; 146 | flex: 1; 147 | 148 | &:focus { 149 | outline: none; 150 | border: 1px solid darken(#dadada, 20%); 151 | box-shadow: 0 0 0 1px darken(#dadada, 20%); 152 | } 153 | } 154 | 155 | .button_toolbar { 156 | margin-top: 10px; 157 | text-align: right; 158 | } 159 | 160 | .button { 161 | position: relative; 162 | display: inline-block; 163 | border: 0; 164 | height: 36px; 165 | line-height: 38px; 166 | padding: 0 20px; 167 | border-radius: 2px; 168 | background: white; 169 | box-shadow: 0 4px 0 #d9d9d8; 170 | user-select: none; 171 | font-family: rangeregular; 172 | color: $link_color; 173 | font-size: 14px; 174 | 175 | &:focus { 176 | outline: none; 177 | } 178 | 179 | &:active { 180 | background: darken(#f0f0f0, 5%); 181 | box-shadow: 0 2px 0 darken(#d9d9d8, 5%); 182 | top: 2px; 183 | } 184 | } 185 | 186 | -------------------------------------------------------------------------------- /worker_suffix.coffee: -------------------------------------------------------------------------------- 1 | 2 | p = new Promise (resolve) -> 3 | Module.onRuntimeInitialized = resolve 4 | 5 | @onmessage = (e) -> 6 | [id, action, code] = e.data 7 | switch action 8 | when "compile" 9 | p.then -> 10 | Module.print = console.log 11 | res = Module.ccall "compile_moonscript", "string", ["string"], [code] 12 | @postMessage [id, res] 13 | when "execute" 14 | p.then -> 15 | buffer = [] 16 | 17 | Module.print = (line) -> 18 | buffer.push line 19 | 20 | res = Module.ccall "run_moonscript", "string", ["string"], [code] 21 | 22 | buffer.push res 23 | @postMessage [id, buffer.join "\n"] 24 | 25 | --------------------------------------------------------------------------------