├── .gitignore ├── .npmignore ├── bin ├── build ├── jisp ├── jisp-dev └── jisp-src ├── browser └── jisp.js ├── build.jisp ├── dev └── jisp │ ├── browser.js │ ├── command.js │ ├── functions.js │ ├── index.js │ ├── jisp.js │ ├── lex.js │ ├── macros.js │ ├── operators.js │ ├── optparse.js │ ├── parse.js │ ├── register.js │ ├── repl.js │ ├── tokenise.js │ ├── uniq.js │ ├── util.js │ └── utils.js ├── lib └── jisp │ ├── browser.js │ ├── command.js │ ├── functions.js │ ├── index.js │ ├── jisp.js │ ├── lex.js │ ├── macros.js │ ├── operators.js │ ├── optparse.js │ ├── parse.js │ ├── register.js │ ├── repl.js │ ├── tokenise.js │ ├── uniq.js │ └── utils.js ├── license ├── package.json ├── readme.md ├── register.js └── src ├── browser.jisp ├── command.jisp ├── functions.jisp ├── index.jisp ├── jisp.jisp ├── lex.jisp ├── macros.jisp ├── operators.jisp ├── optparse.jisp ├── parse.jisp ├── register.jisp ├── repl.jisp ├── tokenise.jisp ├── uniq.jisp └── utils.jisp /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.zip 10 | *.vi 11 | *~ 12 | 13 | # OS or Editor folders 14 | .DS_Store 15 | ._* 16 | Thumbs.db 17 | .cache 18 | .project 19 | .settings 20 | .tmproj 21 | *.esproj 22 | nbproject 23 | *.sublime-project 24 | *.sublime-workspace 25 | .idea 26 | 27 | # grunt-html-validation 28 | validation-status.json 29 | validation-report.json 30 | 31 | # Folders to ignore 32 | node_modules 33 | bower_components 34 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # directories 2 | dev 3 | src 4 | bower_components 5 | 6 | # files in root dir 7 | build.jisp 8 | 9 | # files in bin 10 | bin/jisp-dev 11 | bin/jisp-src 12 | bin/build 13 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // lib 4 | require('../register'); 5 | 6 | require('../build.jisp'); 7 | -------------------------------------------------------------------------------- /bin/jisp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // lib 4 | require('../lib/jisp/command').run(); 5 | -------------------------------------------------------------------------------- /bin/jisp-dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // dev 4 | require('../dev/jisp/command').run(); 5 | -------------------------------------------------------------------------------- /bin/jisp-src: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // src 4 | require('../register'); 5 | require('../src/command').run(); 6 | -------------------------------------------------------------------------------- /build.jisp: -------------------------------------------------------------------------------- 1 | (= fs (require "fs") 2 | args (get (require "yargs") "argv")) 3 | 4 | ; Accepted arguments: 5 | ; no arguments -- rebuild dev with dev 6 | ; -r -- rebuild dev with stable 7 | ; -s -- rebuild stable with dev 8 | 9 | (= files `("index" 10 | "functions" 11 | "utils" 12 | "operators" 13 | "tokenise" 14 | "lex" 15 | "parse" 16 | "register" 17 | "repl" 18 | "optparse" 19 | "command" 20 | "macros" 21 | "uniq" 22 | "jisp" 23 | "browser")) 24 | 25 | (= filesBrowser `("utils" 26 | "functions" 27 | "operators" 28 | "tokenise" 29 | "lex" 30 | "parse" 31 | "macros" 32 | "uniq" 33 | "jisp" 34 | "browser")) 35 | 36 | (def buildFile compiler filename srcDir destDir (do 37 | (= srcPath (+ srcDir filename ".jisp") 38 | destPath (+ destDir filename ".js") 39 | src (fs.readFileSync srcPath "utf8")) 40 | (prn (+ "-- compiling " filename "...")) 41 | (= js (compiler.compile src)) 42 | (fs.writeFileSync destPath js "utf8"))) 43 | 44 | (def build jisp srcDir destDir (do 45 | (prn "-- building...") 46 | (for filename files (buildFile jisp filename srcDir destDir)) 47 | (prn "-- if you're reading this, compilation has succeeded!"))) 48 | 49 | (if args.r 50 | (do 51 | ; Load compiler 52 | (prn "-- trying to load stable compiler...") 53 | (= jisp (require "./lib/jisp/jisp")) 54 | ; Build with stable 55 | (prn "-- rebuilding dev with stable...") 56 | (build jisp "./src/" "./dev/jisp/")) 57 | (elif args.s (do 58 | ; Load compiler 59 | (prn "-- trying to load unstable compiler...") 60 | (= jisp_unstable (require "./dev/jisp/jisp")) 61 | ; Build with unstable 62 | (prn "-- trying to build lib with unstable compiler...") 63 | (build jisp_unstable "./src/" "./lib/jisp/"))) 64 | (do 65 | ; Load compiler 66 | (prn "-- trying to load unstable compiler...") 67 | (= jisp_unstable (require "./dev/jisp/jisp")) 68 | ; Build with unstable 69 | (prn "-- trying to build dev with unstable compiler...") 70 | (build jisp_unstable "./src/" "./dev/jisp/") 71 | (prn "-- when testing the unstable version, recompile at least twice!"))) 72 | 73 | ; Build the concatenated version for the browser 74 | ; Copied from the CoffeeScript cakefile 75 | 76 | (= code "") 77 | 78 | (for name filesBrowser 79 | (+= code (+ 80 | "require['./" name "'] = (function() { 81 | var exports = {}, module = {exports: exports}; 82 | " (fs.readFileSync (+ "./dev/jisp/" name ".js")) " 83 | return module.exports; 84 | })();"))) 85 | 86 | (= code (+ 87 | "(function(root) { 88 | var jisp = function() { 89 | function require(path) { return require[path]; } 90 | " code " 91 | return require['./jisp']; 92 | }(); 93 | root.jisp = jisp; 94 | }(this));")) 95 | 96 | (fs.writeFileSync "./browser/jisp.js" code) 97 | (prn "-- if you're reading this, concat build has succeeded!") 98 | 99 | (try (do (fs.writeFileSync "./node_modules/jisp/browser/jisp.js" code) 100 | (prn "-- replaced the browser module in ./node_modules/jisp/browser/jisp.js for gh-pages testing"))) 101 | -------------------------------------------------------------------------------- /dev/jisp/browser.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var jisp, compile; 3 | jisp = require("./jisp"); 4 | jisp.require = require; 5 | compile = jisp.compile; 6 | jisp.eval = (function(code, options) { 7 | if ((typeof options === 'undefined')) options = {}; 8 | options.wrap = false; 9 | return eval(compile(code, options)); 10 | }); 11 | jisp.run = (function(code, options) { 12 | var compiled; 13 | if ((typeof options === 'undefined')) options = {}; 14 | options.wrap = false; 15 | compiled = compile(code, options); 16 | return Function(compile(code, options))(); 17 | }); 18 | if ((typeof window === 'undefined')) return; 19 | jisp.load = (function(url, callback, options, hold) { 20 | var xhr; 21 | if ((typeof options === 'undefined')) options = {}; 22 | if ((typeof hold === 'undefined')) hold = false; 23 | options.sourceFiles = [url]; 24 | xhr = (window.ActiveXObject ? new window.ActiveXObject("Microsoft.XMLHTTP") : new window.XMLHttpRequest()); 25 | xhr.open("GET", url, true); 26 | if (("overrideMimeType" in xhr)) xhr.overrideMimeType("text/plain"); 27 | xhr.onreadystatechange = (function() { 28 | var param; 29 | if ((xhr.readyState === 4)) { 30 | if ((xhr.status === 0 || xhr.status === 200)) { 31 | param = [xhr.responseText, options]; 32 | if (!hold) jisp.run.apply(jisp, [].concat(param)); 33 | } else { 34 | throw new Error(("Could not load " + url)); 35 | } 36 | } 37 | return (callback ? callback(param) : undefined); 38 | }); 39 | return xhr.send(null); 40 | }); 41 | 42 | function runScripts() { 43 | var scripts, jisps, index, s, i, script, _i, _ref, _ref0; 44 | scripts = window.document.getElementsByTagName("script"); 45 | jisps = []; 46 | index = 0; 47 | _ref = scripts; 48 | for (_i = 0; _i < _ref.length; ++_i) { 49 | s = _ref[_i]; 50 | if ((s.type === "text/jisp")) jisps.push(s); 51 | } 52 | 53 | function execute() { 54 | var param, _ref0; 55 | param = jisps[index]; 56 | if ((param instanceof Array)) { 57 | jisp.run.apply(jisp, [].concat(param)); 58 | ++index; 59 | _ref0 = execute(); 60 | } else { 61 | _ref0 = undefined; 62 | } 63 | return _ref0; 64 | } 65 | execute; 66 | _ref0 = jisps; 67 | for (i = 0; i < _ref0.length; ++i) { 68 | script = _ref0[i]; 69 | (function(script, i) { 70 | var options, _ref1; 71 | options = {}; 72 | if (script.src) { 73 | _ref1 = jisp.load(script.src, (function(param) { 74 | jisps[i] = param; 75 | return execute(); 76 | }), options, true); 77 | } else { 78 | options.sourceFiles = ["embedded"]; 79 | _ref1 = (jisps[i] = [script.innerHTML, options]); 80 | } 81 | return _ref1; 82 | })(script, i); 83 | } 84 | return execute(); 85 | } 86 | runScripts; 87 | return window.addEventListener ? window.addEventListener("DOMContentLoaded", runScripts, false) : window.attachEvent("onload", runScripts); 88 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/command.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var fs, path, mkdirp, spawn, exec, EventEmitter, jisp, utils, optparse, useWinPathSep, banner, switches, opts, sources, sourceCode, notSources, optionParser, joinTimeout, compileJoin; 3 | fs = require("fs"); 4 | path = require("path"); 5 | mkdirp = require("mkdirp"); 6 | spawn = require("child_process").spawn; 7 | exec = require("child_process").exec; 8 | EventEmitter = require("events").EventEmitter; 9 | jisp = require("./jisp"); 10 | utils = require("./utils"); 11 | optparse = require("./optparse"); 12 | useWinPathSep = path.sep === "\\ ".slice(0, 1); 13 | utils.extend(jisp, new EventEmitter()); 14 | 15 | function printLine(line) { 16 | return process.stdout.write(line + "\n"); 17 | } 18 | printLine; 19 | 20 | function printWarn(line) { 21 | return process.stderr.write(line + "\n"); 22 | } 23 | printWarn; 24 | 25 | function hidden(file) { 26 | return /^\.|~$/.test(file); 27 | } 28 | hidden; 29 | banner = "\nUsage: jisp [options] path/to/script.jisp -- [args]\n\nWhen called without options, compiles your script and prints the output to stdout."; 30 | switches = [ 31 | ["-c", "--compile", "compile to JavaScript and save as .js files"], 32 | ["-o", "--output [dir]", "set the output directory for compiled JavaScript"], 33 | ["-i", "--interactive", "run an interactive jisp REPL (this is the default with no options and arguments)"], 34 | ["-v", "--version", "display the version number"] 35 | ]; 36 | opts = {}; 37 | sources = []; 38 | sourceCode = []; 39 | notSources = {}; 40 | optionParser = null; 41 | 42 | function run() { 43 | var replCliOpts, literals, source, _i, _res, _ref, _ref0; 44 | parseOptions(); 45 | replCliOpts = { 46 | useGlobal: true 47 | }; 48 | if (opts.version) return version(); 49 | if ((opts.interactive || !opts.arguments.length)) return require("./repl").start(replCliOpts); 50 | literals = (opts.run ? opts.arguments.splice(1) : []); 51 | process.argv = process.argv.slice(0, 1).concat(literals); 52 | process.argv[0] = 'jisp'; 53 | if (opts.output) opts.output = path.resolve(opts.output); 54 | _res = []; 55 | _ref = opts.arguments; 56 | for (_i = 0; _i < _ref.length; ++_i) { 57 | source = _ref[_i]; 58 | source = path.resolve(source); 59 | if (typeof(_ref0 = compilePath(source, true, source)) !== 'undefined') _res.push(_ref0); 60 | } 61 | return _res; 62 | } 63 | exports.run = run; 64 | 65 | function compilePath(source, topLevel, base) { 66 | var stats, files, file, code, _i, _res, _ref, _ref0, _ref1, _ref2; 67 | if ((([].indexOf.call(sources, source) >= 0) || (!topLevel && (notSources[source] || hidden(source))))) undefined; 68 | try { 69 | stats = fs.statSync(source); 70 | } catch (err) { 71 | if ((err.code === "ENOENT")) { 72 | console.error("File not found:" + source); 73 | process.exit(1); 74 | } 75 | throw err; 76 | } 77 | if (stats.isDirectory()) { 78 | if ((path.basename(source) === "node_modules")) { 79 | _ref1 = (notSources[source] = true); 80 | } else if (opts.run) { 81 | _ref1 = compilePath(findDirectoryIndex(source), topLevel, base); 82 | } else { 83 | try { 84 | files = fs.readdirSync(source); 85 | } catch (err) { 86 | if ((err.code === "ENOENT")) {} else { 87 | throw err; 88 | } 89 | } 90 | _res = []; 91 | _ref = files; 92 | for (_i = 0; _i < _ref.length; ++_i) { 93 | file = _ref[_i]; 94 | if (typeof(_ref0 = compilePath(path.join(source, file), false, base)) !== 'undefined') _res.push(_ref0); 95 | } 96 | _ref1 = _res; 97 | } 98 | _ref2 = _ref1; 99 | } else if (topLevel || utils.isJisp(source)) { 100 | sources.push(source); 101 | sourceCode.push(null); 102 | delete notSources[source]; 103 | try { 104 | code = fs.readFileSync(source); 105 | } catch (err) { 106 | if ((err.code === "ENOENT")) { 107 | return; 108 | } else { 109 | throw err; 110 | } 111 | } 112 | _ref2 = compileScript(source, code.toString(), base); 113 | } else { 114 | _ref2 = (notSources[source] = true); 115 | } 116 | return _ref2; 117 | } 118 | compilePath; 119 | 120 | function findDirectoryIndex(source) { 121 | var ext, index, _i, _ref, _ref0; 122 | _ref = jisp.fileExtensions; 123 | for (_i = 0; _i < _ref.length; ++_i) { 124 | ext = _ref[_i]; 125 | index = path.join(source, "index" + ext); 126 | try { 127 | if (fs.statSync(index).isFile()) { 128 | return _ref0 = index; 129 | } else { 130 | _ref0 = undefined; 131 | } 132 | _ref0; 133 | } catch (err) { 134 | if (!(err.code === "ENOENT")) throw err; 135 | } 136 | } 137 | console.error("Missing index.jisp in " + source); 138 | return process.exit(1); 139 | } 140 | findDirectoryIndex; 141 | 142 | function compileScript(file, input, base) { 143 | var o, options, task, t, compiled, message, _ref, _ref0; 144 | if ((typeof base === 'undefined')) base = null; 145 | o = opts; 146 | options = compileOptions(file, base); 147 | try { 148 | t = (task = { 149 | file: file, 150 | input: input, 151 | options: options 152 | }); 153 | jisp.emit("compile", task); 154 | if (o.run) { 155 | jisp.register(); 156 | _ref = jisp.run(t.input, t.options); 157 | } else { 158 | compiled = jisp.compile(t.input); 159 | t.output = compiled; 160 | jisp.emit("success", task); 161 | _ref = o.compile ? writeJs(base, t.file, t.output, options.jsPath) : printLine(t.output.trim()); 162 | } 163 | _ref0 = _ref; 164 | } catch (err) { 165 | jisp.emit("failure", err, task); 166 | if (jisp.listeners("failure").length) undefined; 167 | message = err.stack || err.toString(); 168 | printWarn(message); 169 | _ref0 = process.exit(1); 170 | } 171 | return _ref0; 172 | } 173 | compileScript; 174 | 175 | function compileStdin() { 176 | var code, stdin; 177 | code = ""; 178 | stdin = process.openStdin(); 179 | stdin.on("data", (function(buffer) { 180 | return (buffer ? (code += buffer.toString()) : undefined); 181 | })); 182 | return stdin.on("end", (function() { 183 | return compileScript(null, code); 184 | })); 185 | } 186 | compileStdin; 187 | joinTimeout = null; 188 | compileJoin = (function() { 189 | var _ref; 190 | if (!sourceCode.some((function(code) { 191 | return (code === null); 192 | }))) { 193 | clearTimeout(joinTimeout); 194 | _ref = (joinTimeout = wait(100, (function() { 195 | return compileScript(opts.join, sourceCode.join("\n"), opts.join); 196 | }))); 197 | } else { 198 | _ref = undefined; 199 | } 200 | return _ref; 201 | }); 202 | 203 | function outputPath(source, base, extension) { 204 | var basename, srcDir, dir, _ref; 205 | if ((typeof extension === 'undefined')) extension = ".js"; 206 | basename = utils.baseFileName(source, true, useWinPathSep); 207 | srcDir = path.dirname(source); 208 | if (!opts.output) { 209 | _ref = srcDir; 210 | } else if (source === base) { 211 | _ref = opts.output; 212 | } else { 213 | _ref = path.join(opts.output, path.relative(base, srcDir)); 214 | } 215 | dir = _ref; 216 | return path.join(dir, basename + extension); 217 | } 218 | outputPath; 219 | 220 | function writeJs(base, sourcePath, js, jsPath) { 221 | var jsDir; 222 | jsDir = path.dirname(jsPath); 223 | js = js; 224 | 225 | function compile() { 226 | var _ref; 227 | if (opts.compile) { 228 | if ((js.length <= 0)) js = " "; 229 | _ref = fs.writeFile(jsPath, js, (function(err) { 230 | return (err ? printLine(err.message) : undefined); 231 | })); 232 | } else { 233 | _ref = undefined; 234 | } 235 | return _ref; 236 | } 237 | compile; 238 | return fs.exists(jsDir, (function(itExists) { 239 | return (itExists ? compile() : mkdirp(jsDir, compile)); 240 | })); 241 | } 242 | writeJs; 243 | 244 | function wait(milliseconds, func) { 245 | return setTimeout(func, milliseconds); 246 | } 247 | wait; 248 | 249 | function parseOptions() { 250 | var o; 251 | optionParser = new optparse.OptionParser(switches, banner); 252 | opts = optionParser.parse(process.argv.slice(2)); 253 | o = opts; 254 | o.compile = o.compile || !!o.output; 255 | return (o.run = !o.compile); 256 | } 257 | parseOptions; 258 | 259 | function compileOptions(filename, base) { 260 | var answer, cwd, jsPath, jsDir, _ref, _ref0; 261 | answer = { 262 | filename: filename 263 | }; 264 | if (!filename) { 265 | _ref0 = answer; 266 | } else { 267 | if (base) { 268 | cwd = process.cwd(); 269 | jsPath = outputPath(filename, base); 270 | jsDir = path.dirname(jsPath); 271 | _ref = (answer = utils.merge(answer, { 272 | jsPath: jsPath, 273 | sourceRoot: path.relative(jsDir, cwd), 274 | sourceFiles: [path.relative(cwd, filename)], 275 | generatedFile: utils.baseFileName(jsPath, false, useWinPathSep) 276 | })); 277 | } else { 278 | _ref = (answer = utils.merge(answer, { 279 | sourceRoot: "", 280 | sourceFiles: [utils.baseFileName(filename, false, useWinPathSep)], 281 | generatedFile: utils.baseFileName(filename, true, useWinPathSep) + ".js" 282 | })); 283 | } 284 | _ref0 = _ref; 285 | } 286 | return _ref0; 287 | } 288 | compileOptions; 289 | 290 | function version() { 291 | return printLine("jisp version " + jisp.version); 292 | } 293 | return version; 294 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/functions.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | function concat() { 3 | var _res, lst, _i, _i0, _ref; 4 | var lists = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 5 | _res = []; 6 | _ref = lists; 7 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 8 | lst = _ref[_i0]; 9 | _res = _res.concat(lst); 10 | } 11 | return _res; 12 | } 13 | exports.concat = concat; 14 | 15 | function list() { 16 | var _i; 17 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 18 | return [].concat(args); 19 | } 20 | exports.list = list; 21 | 22 | function range(start, end) { 23 | var a, _res, _ref; 24 | if ((typeof end === 'undefined')) { 25 | end = start; 26 | start = 0; 27 | } 28 | _res = []; 29 | while (true) { 30 | if ((start <= end)) { 31 | a = start; 32 | ++start; 33 | _ref = a; 34 | } else { 35 | _ref = undefined; 36 | break; 37 | } 38 | if (typeof _ref !== 'undefined') _res.push(_ref); 39 | } 40 | return _res; 41 | } 42 | return exports.range = range; 43 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/index.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var key, val, _ref; 3 | _ref = require("./jisp"); 4 | for (key in _ref) { 5 | val = _ref[key]; 6 | exports[key] = val; 7 | } 8 | return; 9 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/lex.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | function concat() { 3 | var _res, lst, _i, _i0, _ref; 4 | var lists = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 5 | _res = []; 6 | _ref = lists; 7 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 8 | lst = _ref[_i0]; 9 | _res = _res.concat(lst); 10 | } 11 | return _res; 12 | } 13 | var utils, pr, spr, isList, isAtom, isaString, isNum, isRegex, isIdentifier, isString, isKey, isDotName, isBracketName, isBracketString, isPropSyntax; 14 | utils = require("./utils"); 15 | pr = utils.pr; 16 | spr = utils.spr; 17 | isList = utils.isList; 18 | isAtom = utils.isAtom; 19 | isaString = utils.isaString; 20 | isNum = utils.isNum; 21 | isRegex = utils.isRegex; 22 | isIdentifier = utils.isIdentifier; 23 | isString = utils.isString; 24 | isKey = utils.isKey; 25 | isDotName = utils.isDotName; 26 | isBracketName = utils.isBracketName; 27 | isBracketString = utils.isBracketString; 28 | isPropSyntax = utils.isPropSyntax; 29 | 30 | function printConditions(conditions) { 31 | var cond, _i, _res, _ref, _ref0; 32 | _res = []; 33 | _ref = concat(conditions); 34 | for (_i = 0; _i < _ref.length; ++_i) { 35 | cond = _ref[_i]; 36 | if (((typeof cond === "function") && ((typeof cond !== 'undefined') && (typeof cond.name !== 'undefined')))) { 37 | _ref0 = cond.name; 38 | } else if (isList(cond)) { 39 | _ref0 = printConditions(cond); 40 | } else { 41 | _ref0 = pr(cond); 42 | } 43 | if (typeof _ref0 !== 'undefined') _res.push(_ref0); 44 | } 45 | return _res 46 | .join(" "); 47 | } 48 | printConditions; 49 | 50 | function maketest(condition) { 51 | var _ref; 52 | if ((typeof condition === "function")) { 53 | _ref = (function(tokens) { 54 | return condition(tokens[0]); 55 | }); 56 | } else if (isRegex(condition)) { 57 | _ref = (function(tokens) { 58 | return condition.test(tokens[0]); 59 | }); 60 | } else if (isAtom(condition)) { 61 | _ref = (function(tokens) { 62 | return (tokens[0] === condition); 63 | }); 64 | } else if (isList(condition)) { 65 | _ref = (function(tokens) { 66 | var i, cond, _res, _ref0, _ref1; 67 | _res = []; 68 | _ref0 = condition; 69 | for (i = 0; i < _ref0.length; ++i) { 70 | cond = _ref0[i]; 71 | if (!maketest(cond)(tokens.slice(i))) { 72 | return _ref1 = false; 73 | } else { 74 | _ref1 = undefined; 75 | } 76 | if (typeof _ref1 !== 'undefined') _res.push(_ref1); 77 | } 78 | return (_res ? true : undefined); 79 | }); 80 | } else { 81 | _ref = undefined; 82 | throw Error("can't test against " + pr(condition)); 83 | } 84 | return _ref; 85 | } 86 | maketest; 87 | 88 | function demand(tokens) { 89 | var conditions, modes, condition, mode, test, err, _i; 90 | var args = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 91 | conditions = []; 92 | modes = []; 93 | while (args.length > 0) { 94 | condition = args.shift(); 95 | mode = args.shift(); 96 | conditions.push(condition); 97 | modes.push(mode); 98 | test = maketest(condition); 99 | if (test(tokens)) return lex(tokens, mode); 100 | } 101 | err = ((typeof tokens[0] === 'undefined') ? Error("unexpected end of input, probably missing ) ] }") : Error("unexpected " + pr(tokens[0]) + " in possible modes: " + modes.join(" | ") + "\n\nTested against: " + printConditions(conditions) + "\n\nTokens: " + spr(tokens.slice(0, 10)) + ((tokens.length > 10) ? " ..." : " "))); 102 | throw err; 103 | } 104 | demand; 105 | 106 | function expect(tokens) { 107 | var condition, mode, test, _i, _ref; 108 | var args = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 109 | while (args.length > 0) { 110 | condition = args.shift(); 111 | mode = args.shift(); 112 | test = maketest(condition); 113 | if (test(tokens)) { 114 | return _ref = lex(tokens, mode); 115 | } else { 116 | _ref = undefined; 117 | } 118 | _ref; 119 | } 120 | return undefined; 121 | } 122 | expect; 123 | 124 | function forbid(tokens) { 125 | var condition, _i, _i0, _res, _ref, _ref0; 126 | var args = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 127 | _res = []; 128 | _ref = args; 129 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 130 | condition = _ref[_i0]; 131 | if (maketest(condition)(tokens)) { 132 | _ref0 = undefined; 133 | throw Error("unexpected " + pr(tokens[0])); 134 | } else { 135 | _ref0 = undefined; 136 | } 137 | if (typeof _ref0 !== 'undefined') _res.push(_ref0); 138 | } 139 | return _res; 140 | } 141 | forbid; 142 | 143 | function nextProp(tokens) { 144 | return expect(tokens, "[", "property", isPropSyntax, "property"); 145 | } 146 | nextProp; 147 | 148 | function grabProperties(tokens, lexed) { 149 | var prop; 150 | while (prop = nextProp(tokens)) { 151 | ((typeof lexed === 'undefined') ? (lexed = ["get", prop]) : (lexed = ["get", lexed, prop])); 152 | } 153 | return lexed; 154 | } 155 | grabProperties; 156 | 157 | function lex(tokens, mode) { 158 | var lexed, prop, key, _ref, _ref0; 159 | if ((typeof mode === 'undefined')) mode = "default"; 160 | switch (mode) { 161 | case "default": 162 | lexed = []; 163 | if ((typeof(prop = grabProperties(tokens)) !== 'undefined')) lexed.push(prop); 164 | while (tokens.length > 0) { 165 | lexed.push(demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", "...", "spread", "…", "spread", isaString, "atom", undefined, "drop")); 166 | } 167 | _ref = grabProperties(tokens, lexed); 168 | break; 169 | case "list": 170 | demand(tokens, "(", "drop"); 171 | lexed = []; 172 | if ((typeof(prop = grabProperties(tokens)) !== 'undefined')) lexed.push(prop); 173 | while (tokens[0] !== ")") { 174 | lexed.push(demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", "...", "spread", "…", "spread", isaString, "atom")); 175 | } 176 | demand(tokens, ")", "drop"); 177 | _ref = grabProperties(tokens, lexed); 178 | break; 179 | case "emptyhash": 180 | demand(tokens, "(", "drop"); 181 | demand(tokens, ":", "drop"); 182 | demand(tokens, ")", "drop"); 183 | _ref = grabProperties(tokens, {}); 184 | break; 185 | case "hash": 186 | lexed = {}; 187 | demand(tokens, "(", "drop"); 188 | while (tokens[0] !== ")") { 189 | key = demand(tokens, isKey, "key"); 190 | demand(tokens, ":", "drop"); 191 | prop = demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", isaString, "atom"); 192 | lexed[key] = prop; 193 | } 194 | demand(tokens, ")", "drop"); 195 | _ref = grabProperties(tokens, lexed); 196 | break; 197 | case "property": 198 | if (isDotName(tokens[0])) { 199 | _ref0 = demand(tokens, isDotName, "drop"); 200 | } else if (isBracketName(tokens[0]) || isBracketString(tokens[0])) { 201 | _ref0 = demand(tokens, isBracketName, "drop", isBracketString, "drop") 202 | .slice(1, -1); 203 | } else { 204 | demand(tokens, "[", "drop"); 205 | prop = demand(tokens, "(", "list", ",", "quote", isIdentifier, "atom", isNum, "atom", isString, "atom"); 206 | demand(tokens, "]", "drop"); 207 | _ref0 = prop; 208 | } 209 | _ref = _ref0; 210 | break; 211 | case "quote": 212 | demand(tokens, "`", "drop"); 213 | _ref = (lexed = ["quote", demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", isaString, "atom")]); 214 | break; 215 | case "unquote": 216 | demand(tokens, ",", "drop"); 217 | _ref = ["unquote", grabProperties(tokens, demand(tokens, "(", "list", "`", "quote", "...", "spread", "…", "spread", isIdentifier, "atom"))]; 218 | break; 219 | case "spread": 220 | demand(tokens, "...", "drop", "…", "drop"); 221 | _ref = ["spread", grabProperties(tokens, demand(tokens, "(", "list", "`", "quote", isIdentifier, "atom"))]; 222 | break; 223 | case "key": 224 | key = demand(tokens, isKey, "drop"); 225 | forbid("[", isPropSyntax); 226 | _ref = key; 227 | break; 228 | case "atom": 229 | _ref = grabProperties(tokens, demand(tokens, isaString, "drop")); 230 | break; 231 | case "drop": 232 | _ref = tokens.shift(); 233 | break; 234 | default: 235 | _ref = undefined; 236 | throw Error("unspecified lex mode: " + mode); 237 | } 238 | return _ref; 239 | } 240 | lex; 241 | return module.exports = lex; 242 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/macros.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var macHash = function() { 3 | var buffer, _i, _ref; 4 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 5 | if ((args.length === 1)) { 6 | _ref = ["do", ["=", "#_res", {}, "#_ref", args[0]], 7 | ["while", [">", "#_ref.length", 0], 8 | ["=", ["get", "#_res", ["#_ref.shift"]], 9 | ["#_ref.shift"] 10 | ] 11 | ], "#_res" 12 | ]; 13 | } else { 14 | buffer = {}; 15 | while (args.length > 0) { 16 | buffer[args.shift()] = args.shift(); 17 | } 18 | _ref = buffer; 19 | } 20 | return _ref; 21 | }; 22 | var macConcatHash = function() { 23 | var arg, _i, _i0, _res, _ref, _ref0; 24 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 25 | _res = []; 26 | _ref = args; 27 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 28 | arg = _ref[_i0]; 29 | if (typeof(_ref0 = ["spread", arg]) !== 'undefined') _res.push(_ref0); 30 | } 31 | return [":", [].concat(["concat"]).concat(_res)]; 32 | }; 33 | var macPrn = function() { 34 | var _i; 35 | var x = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 36 | return [].concat(["console.log"]).concat(x); 37 | }; 38 | var macCar = function(x) { 39 | var _i; 40 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 41 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 42 | return ["get", x, 0]; 43 | }; 44 | var macCdr = function(x) { 45 | var _i; 46 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 47 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 48 | return [ 49 | ["get", x, "\"slice\""], 1 50 | ]; 51 | }; 52 | var macInit = function(x) { 53 | var _i; 54 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 55 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 56 | return [ 57 | ["get", x, "\"slice\""], 0, -1 58 | ]; 59 | }; 60 | var macLast = function(x) { 61 | var _i; 62 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 63 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 64 | return ["get", [ 65 | ["get", x, "\"slice\""], -1 66 | ], 0]; 67 | }; 68 | var macLet = function() { 69 | var body, names, callArgs, name, _i; 70 | var args = 2 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []); 71 | body = arguments[_i++]; 72 | if (((args.length % 2) !== 0)) throw Error, ("expecting an even number of arguments, got " + args.length); 73 | if ((typeof body === 'undefined')) body = []; 74 | names = []; 75 | callArgs = []; 76 | while (args.length > 0) { 77 | name = args.shift(); 78 | if (true) names.push(name); 79 | callArgs.push(args.shift()); 80 | } 81 | return [].concat([ 82 | [].concat(["fn"]).concat(names).concat([body]) 83 | ]).concat(callArgs); 84 | }; 85 | 86 | function list() { 87 | var _i; 88 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 89 | return [].concat(args); 90 | } 91 | var macExist = function() { 92 | var value, comp, elements, _i, _i0, _res, _ref, _ref0; 93 | var values = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 94 | _res = []; 95 | _ref = values; 96 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 97 | value = _ref[_i0]; 98 | comp = compartmentaliseExist(value); 99 | if (typeof(_ref0 = ((comp.length > 1) ? [].concat(["and"]).concat(comp) : comp[0])) !== 'undefined') _res.push(_ref0); 100 | } 101 | elements = _res; 102 | return ((elements.length > 1) ? [].concat(["or"]).concat(elements) : elements[0]); 103 | }; 104 | var macNotExist = function() { 105 | var value, comp, elements, _i, _i0, _res, _ref, _ref0; 106 | var values = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 107 | _res = []; 108 | _ref = values; 109 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 110 | value = _ref[_i0]; 111 | comp = compartmentaliseNotExist(value); 112 | if (typeof(_ref0 = ((comp.length > 1) ? [].concat(["or"]).concat(comp) : comp[0])) !== 'undefined') _res.push(_ref0); 113 | } 114 | elements = _res; 115 | return ((elements.length > 1) ? [].concat(["and"]).concat(elements) : elements[0]); 116 | }; 117 | var macIsA = function(obj) { 118 | var _i; 119 | var types = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 120 | return [].concat(["is", ["typeof", obj]]).concat(types); 121 | }; 122 | var macIsNa = function(obj) { 123 | var _i; 124 | var types = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 125 | return [].concat(["isnt", ["typeof", obj]]).concat(types); 126 | }; 127 | var macAny = function() { 128 | var value, elements, _i, _i0, _res, _ref, _ref0; 129 | var values = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 130 | _res = []; 131 | _ref = values; 132 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 133 | value = _ref[_i0]; 134 | if (typeof(_ref0 = ["and", ["?", value], value]) !== 'undefined') _res.push(_ref0); 135 | } 136 | elements = _res; 137 | return ((elements.length > 1) ? [].concat(["or"]).concat(elements) : elements[0]); 138 | }; 139 | var utils; 140 | utils = require("./utils"); 141 | exports[":"] = macHash; 142 | exports["::"] = macConcatHash; 143 | exports.prn = macPrn; 144 | exports.car = macCar; 145 | exports.head = macCar; 146 | exports.cdr = macCdr; 147 | exports.tail = macCdr; 148 | exports.init = macInit; 149 | exports.last = macLast; 150 | exports.let = macLet; 151 | 152 | function compartmentaliseExist(form) { 153 | var i, val, split, _ref, _res, _ref0, _ref1; 154 | if ((utils.isList(form) && (form[0] === "get"))) { 155 | _ref = list.apply(list, [].concat(compartmentaliseExist(form[1])).concat([ 156 | ["isnta", form, "'undefined'"] 157 | ])); 158 | } else if ((typeof form === "string") && utils.isIdentifier(form) && !utils.isSpecialValueStr(form)) { 159 | _res = []; 160 | _ref0 = (split = utils.splitName(form)); 161 | for (i = 0; i < _ref0.length; ++i) { 162 | val = _ref0[i]; 163 | if (typeof(_ref1 = ["isnta", split.slice(0, i + 1) 164 | .join(""), "'undefined'" 165 | ]) !== 'undefined') _res.push(_ref1); 166 | } 167 | _ref = _res; 168 | } else { 169 | _ref = [ 170 | ["isnta", form, "'undefined'"] 171 | ]; 172 | } 173 | return _ref; 174 | } 175 | compartmentaliseExist; 176 | exports["?"] = macExist; 177 | 178 | function compartmentaliseNotExist(form) { 179 | var i, val, split, _ref, _res, _ref0, _ref1; 180 | if ((utils.isList(form) && (form[0] === "get"))) { 181 | _ref = list.apply(list, [].concat(compartmentaliseNotExist(form[1])).concat([ 182 | ["isa", form, "'undefined'"] 183 | ])); 184 | } else if ((typeof form === "string") && utils.isIdentifier(form) && !utils.isSpecialValueStr(form)) { 185 | _res = []; 186 | _ref0 = (split = utils.splitName(form)); 187 | for (i = 0; i < _ref0.length; ++i) { 188 | val = _ref0[i]; 189 | if (typeof(_ref1 = ["isa", split.slice(0, i + 1) 190 | .join(""), "'undefined'" 191 | ]) !== 'undefined') _res.push(_ref1); 192 | } 193 | _ref = _res; 194 | } else { 195 | _ref = [ 196 | ["isa", form, "'undefined'"] 197 | ]; 198 | } 199 | return _ref; 200 | } 201 | compartmentaliseNotExist; 202 | exports["?!"] = macNotExist; 203 | exports.isa = macIsA; 204 | exports.isnta = macIsNa; 205 | return exports.any = macAny; 206 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/operators.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var utils, pr, spr, render, isIdentifier, assertForm, operators, singops, op, ops, stateops, opFuncs, _i, _ref, _i0, _ref0, _i1, _ref1; 3 | utils = require("./utils"); 4 | pr = utils.pr; 5 | spr = utils.spr; 6 | render = utils.render; 7 | isIdentifier = utils.isIdentifier; 8 | assertForm = utils.assertForm; 9 | 10 | function makeop(op, zv, min, max, drop) { 11 | if ((typeof min === 'undefined')) min = 0; 12 | if ((typeof max === 'undefined')) max = Infinity; 13 | if ((typeof drop === 'undefined')) drop = false; 14 | return (function(args, innerType) { 15 | var i, arg, res, _ref, _ref0, _ref1; 16 | if (assertForm(args, min, max)) { 17 | if ((args.length === 0)) { 18 | _ref0 = pr(zv); 19 | } else if ((args.length === 1) && (typeof zv !== 'undefined')) { 20 | res = zv + op + spr(args); 21 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 22 | _ref0 = res; 23 | } else if ((args.length === 1) && drop) { 24 | _ref0 = spr(args); 25 | } else if (args.length === 1) { 26 | _ref0 = (op + spr(args)); 27 | } else { 28 | _ref = args; 29 | for (i = 0; i < _ref.length; ++i) { 30 | arg = _ref[i]; 31 | args[i] = pr(arg); 32 | } 33 | res = args.join(" " + op + " "); 34 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 35 | _ref0 = res; 36 | } 37 | _ref1 = _ref0; 38 | } else { 39 | _ref1 = undefined; 40 | } 41 | return _ref1; 42 | }); 43 | } 44 | makeop; 45 | 46 | function makesing(op) { 47 | return (function(args, innerType) { 48 | return (assertForm(args, 1, 1) ? (op + " " + spr(args)) : undefined); 49 | }); 50 | } 51 | makesing; 52 | 53 | function reserved(word) { 54 | throw Error("keyword " + word + " is reserved"); 55 | } 56 | reserved; 57 | 58 | function makestate(op, min, max) { 59 | if ((typeof min === 'undefined')) min = 0; 60 | if ((typeof max === 'undefined')) max = Infinity; 61 | return (function(args, innerType) { 62 | return (assertForm(args, min, max) ? (op + " " + spr(args)) : "undefined"); 63 | }); 64 | } 65 | makestate; 66 | operators = { 67 | "++": (function(args, innerType) { 68 | var _ref, _ref0; 69 | if (assertForm(args, 1, 1)) { 70 | if (!isIdentifier(args[0])) { 71 | _ref = undefined; 72 | throw Error("expecting identifier, got ", spr(args)); 73 | } else { 74 | _ref = ("++" + spr(args)); 75 | } 76 | _ref0 = _ref; 77 | } else { 78 | _ref0 = undefined; 79 | } 80 | return _ref0; 81 | }), 82 | "--": (function(args, innerType) { 83 | var _ref, _ref0; 84 | if (assertForm(args, 1, 1)) { 85 | if (!isIdentifier(args[0])) { 86 | _ref = undefined; 87 | throw Error("expecting identifier, got ", spr(args)); 88 | } else { 89 | _ref = ("--" + spr(args)); 90 | } 91 | _ref0 = _ref; 92 | } else { 93 | _ref0 = undefined; 94 | } 95 | return _ref0; 96 | }), 97 | "is": (function(args, innerType) { 98 | var subj, arg, res, _i, _res, _ref, _ref0, _ref1; 99 | if ((args.length === 0)) { 100 | _ref1 = true; 101 | } else if (args.length === 1) { 102 | _ref1 = ("!!" + spr(args)); 103 | } else { 104 | subj = args.shift(); 105 | _res = []; 106 | _ref = args; 107 | for (_i = 0; _i < _ref.length; ++_i) { 108 | arg = _ref[_i]; 109 | if (typeof(_ref0 = (pr(subj) + " === " + pr(arg))) !== 'undefined') _res.push(_ref0); 110 | } 111 | res = _res 112 | .join(" || "); 113 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 114 | _ref1 = res; 115 | } 116 | return _ref1; 117 | }), 118 | "isnt": (function(args, innerType) { 119 | var subj, arg, res, _i, _res, _ref, _ref0, _ref1; 120 | if ((args.length === 0)) { 121 | _ref1 = false; 122 | } else if (args.length === 1) { 123 | _ref1 = ("!" + spr(args)); 124 | } else { 125 | subj = args.shift(); 126 | _res = []; 127 | _ref = args; 128 | for (_i = 0; _i < _ref.length; ++_i) { 129 | arg = _ref[_i]; 130 | if (typeof(_ref0 = (pr(subj) + " !== " + pr(arg))) !== 'undefined') _res.push(_ref0); 131 | } 132 | res = _res 133 | .join(" && "); 134 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 135 | _ref1 = res; 136 | } 137 | return _ref1; 138 | }), 139 | "or": makeop("||", undefined, 1, Infinity, true), 140 | "and": makeop("&&", undefined, 1, Infinity, true), 141 | "in": (function(args, innerType) { 142 | var res, _ref; 143 | if (assertForm(args, 2, 2)) { 144 | res = "[].indexOf.call(" + pr(args[1]) + ", " + pr(args[0]) + ") >= 0"; 145 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 146 | _ref = res; 147 | } else { 148 | _ref = undefined; 149 | } 150 | return _ref; 151 | }), 152 | "of": makeop("in", undefined, 2, 2), 153 | "new": (function(args, innerType) { 154 | return (assertForm(args, 1) ? ("new " + pr(args.shift()) + "(" + spr(args) + ")") : undefined); 155 | }), 156 | "function": (function() { 157 | return reserved("function"); 158 | }), 159 | "with": (function() { 160 | return reserved("with"); 161 | }) 162 | }; 163 | singops = [ 164 | ["not", "!"], 165 | ["~", "~"], 166 | ["delete", "delete"], 167 | ["typeof", "typeof"], 168 | ["!!", "!!"] 169 | ]; 170 | _ref = singops; 171 | for (_i = 0; _i < _ref.length; ++_i) { 172 | op = _ref[_i]; 173 | operators[op[0]] = makesing(op[1]); 174 | } 175 | ops = [ 176 | ["+", undefined, 1, Infinity, true], 177 | ["-", undefined, 1], 178 | ["*", 1], 179 | ["/", 1], 180 | ["%", undefined, 1], 181 | ["==", "is"], 182 | ["===", "is"], 183 | ["!=", "isnt"], 184 | ["!==", "isnt"], 185 | ["&&", "and"], 186 | ["||", "or"], 187 | ["!", "not"], 188 | [">", undefined, 2], 189 | ["<", undefined, 2], 190 | [">=", undefined, 2], 191 | ["<=", undefined, 2], 192 | ["&", undefined, 2], 193 | ["|", undefined, 2], 194 | ["^", undefined, 2], 195 | ["<<", undefined, 2], 196 | [">>", undefined, 2], 197 | [">>>", undefined, 2], 198 | ["+=", undefined, 2], 199 | ["-=", undefined, 2], 200 | ["*=", undefined, 2], 201 | ["/=", undefined, 2], 202 | ["%=", undefined, 2], 203 | ["<<=", undefined, 2], 204 | [">>=", undefined, 2], 205 | [">>>=", undefined, 2], 206 | ["&=", undefined, 2], 207 | ["^=", undefined, 2], 208 | ["|=", undefined, 2], 209 | ["instanceof", undefined, 2, 2], 210 | [",", undefined, 2, 2] 211 | ]; 212 | _ref0 = ops; 213 | for (_i0 = 0; _i0 < _ref0.length; ++_i0) { 214 | op = _ref0[_i0]; 215 | (typeof op[1] === "string") ? operators[op[0]] = operators[op[1]]: operators[op[0]] = makeop.apply(makeop, [].concat(op)); 216 | } 217 | stateops = [ 218 | ["return", 0, 1], 219 | ["break", 0, 1], 220 | ["continue", 0, 0], 221 | ["throw", 1, 1] 222 | ]; 223 | _ref1 = stateops; 224 | for (_i1 = 0; _i1 < _ref1.length; ++_i1) { 225 | op = _ref1[_i1]; 226 | operators[op[0]] = makestate(op[0]); 227 | } 228 | exports.operators = operators; 229 | opFuncs = {}; 230 | 231 | function add() { 232 | var _i2; 233 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 234 | args.unshift(0); 235 | return ((args.length === 0) ? 0 : args.reduce((function() { 236 | return (arguments[0] + arguments[1]); 237 | }))); 238 | } 239 | add; 240 | 241 | function sub() { 242 | var _i2; 243 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 244 | args.unshift(0); 245 | return ((args.length === 0) ? 0 : args.reduce((function() { 246 | return (arguments[0] - arguments[1]); 247 | }))); 248 | } 249 | sub; 250 | 251 | function mul() { 252 | var _i2; 253 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 254 | args.unshift(1); 255 | return ((args.length === 0) ? 1 : args.reduce((function() { 256 | return (arguments[0] * arguments[1]); 257 | }))); 258 | } 259 | mul; 260 | 261 | function div() { 262 | var _i2; 263 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 264 | args.unshift(1); 265 | return ((args.length === 0) ? 1 : args.reduce((function() { 266 | return (arguments[0] / arguments[1]); 267 | }))); 268 | } 269 | div; 270 | return exports.opFuncs = opFuncs; 271 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/optparse.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var repeat, OptionParser, long_flag, short_flag, multi_flag, optional; 3 | repeat = require("./utils").repeat; 4 | exports.OptionParser = (OptionParser = (function() { 5 | function OptionParser(rules, banner) { 6 | this.banner = banner; 7 | this.rules = buildRules(rules); 8 | return this; 9 | } 10 | OptionParser; 11 | OptionParser.prototype.parse = (function(args) { 12 | var options, skippingArgument, originalArgs, i, arg, pos, isOption, seenNonOptionArg, matchedRule, rule, value, _ref, _i, _ref0; 13 | options = { 14 | arguments: [] 15 | }; 16 | skippingArgument = false; 17 | originalArgs = args; 18 | args = normaliseArguments(args); 19 | _ref = args; 20 | for (i = 0; i < _ref.length; ++i) { 21 | arg = _ref[i]; 22 | if (skippingArgument) { 23 | skippingArgument = false; 24 | continue; 25 | } 26 | if ((arg === "--")) { 27 | pos = originalArgs.indexOf("--"); 28 | options.arguments = options.arguments.concat(originalArgs.slice(pos + 1)); 29 | break; 30 | } 31 | isOption = !!(arg.match(long_flag) || arg.match(short_flag)); 32 | seenNonOptionArg = options.arguments.length > 0; 33 | if (!seenNonOptionArg) { 34 | matchedRule = false; 35 | _ref0 = this.rules; 36 | for (_i = 0; _i < _ref0.length; ++_i) { 37 | rule = _ref0[_i]; 38 | if ((arg === rule.shortFlag || arg === rule.longFlag)) { 39 | value = true; 40 | if (rule.hasArgument) { 41 | skippingArgument = true; 42 | value = args[i + 1]; 43 | } 44 | options[rule.name] = (rule.isList ? options[rule.name] || [].concat(value) : value); 45 | matchedRule = true; 46 | break; 47 | } 48 | } 49 | if ((isOption && !matchedRule)) throw new Error(("unrecognised option: " + arg)); 50 | } 51 | if ((seenNonOptionArg || !isOption)) options.arguments.push(arg); 52 | } 53 | return options; 54 | }); 55 | OptionParser.prototype.help = (function() { 56 | var lines, rule, spaces, letPart, _i, _ref; 57 | lines = []; 58 | if (this.banner) lines.unshift(this.banner + "\n"); 59 | _ref = this.rules; 60 | for (_i = 0; _i < _ref.length; ++_i) { 61 | rule = _ref[_i]; 62 | spaces = 15 - rule.longFlag.length; 63 | spaces = ((spaces > 0) ? repeat(" ", spaces) : ""); 64 | letPart = (rule.shortFlag ? (rule.shortFlag + ", ") : " "); 65 | lines.push(" " + letPart + rule.longFlag + spaces + rule.description); 66 | } 67 | return ("\n" + lines.join("\n") + "\n"); 68 | }); 69 | return OptionParser; 70 | })()); 71 | long_flag = /^(--\w[\w\-]*)/; 72 | short_flag = /^(-\w)$/; 73 | multi_flag = /^-(\w{2,})/; 74 | optional = /\[(\w+(\*?))\]/; 75 | 76 | function buildRules(rules) { 77 | var tuple, _i, _res, _ref, _ref0; 78 | _res = []; 79 | _ref = rules; 80 | for (_i = 0; _i < _ref.length; ++_i) { 81 | tuple = _ref[_i]; 82 | if ((tuple.length < 3)) tuple.unshift(null); 83 | if (typeof(_ref0 = buildRule.apply(buildRule, [].concat(tuple))) !== 'undefined') _res.push(_ref0); 84 | } 85 | return _res; 86 | } 87 | buildRules; 88 | 89 | function buildRule(shortFlag, longFlag, description, options) { 90 | var match; 91 | if ((typeof options === 'undefined')) options = {}; 92 | match = longFlag.match(optional); 93 | longFlag = longFlag.match(long_flag)[1]; 94 | return { 95 | name: longFlag.substr(2), 96 | shortFlag: shortFlag, 97 | longFlag: longFlag, 98 | description: description, 99 | hasArgument: !!(match && match[1]), 100 | isList: !!(match && match[2]) 101 | } 102 | } 103 | buildRule; 104 | 105 | function normaliseArguments(args) { 106 | var result, arg, match, l, _i, _ref, _i0, _ref0; 107 | args = args.slice(0); 108 | result = []; 109 | _ref = args; 110 | for (_i = 0; _i < _ref.length; ++_i) { 111 | arg = _ref[_i]; 112 | if ((match = arg.match(multi_flag))) { 113 | _ref0 = match[1].split(""); 114 | for (_i0 = 0; _i0 < _ref0.length; ++_i0) { 115 | l = _ref0[_i0]; 116 | result.push("-" + l); 117 | } 118 | } else { 119 | result.push(arg); 120 | } 121 | } 122 | return result; 123 | } 124 | return normaliseArguments; 125 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/parse.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var utils; 3 | utils = require("./utils"); 4 | 5 | function parse(form) { 6 | var i, val, key, _ref, _ref0, _ref1; 7 | if (utils.isList(form)) { 8 | _ref = form; 9 | for (i = 0; i < _ref.length; ++i) { 10 | val = _ref[i]; 11 | form[i] = parse(val); 12 | } 13 | _ref0 = form; 14 | } else if (utils.isHash(form)) { 15 | _ref1 = form; 16 | for (key in _ref1) { 17 | val = _ref1[key]; 18 | form[key] = parse(val); 19 | } 20 | _ref0 = form; 21 | } else { 22 | form = utils.typify(form); 23 | _ref0 = (/^#(\d+)/.test(form) ? form.replace(/^#(\d+)/, "arguments[$1]") : form); 24 | } 25 | return _ref0; 26 | } 27 | return module.exports = parse; 28 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/register.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var child_process, path, utils, jisp, ext, _i, _ref; 3 | child_process = require("child_process"); 4 | path = require("path"); 5 | utils = require("./utils"); 6 | jisp = require("./jisp"); 7 | 8 | function loadFile(module, filename) { 9 | return module._compile(jisp.compileFile(filename), filename); 10 | } 11 | loadFile; 12 | if (require.extensions) { 13 | _ref = jisp.fileExtensions; 14 | for (_i = 0; _i < _ref.length; ++_i) { 15 | ext = _ref[_i]; 16 | require.extensions[ext] = loadFile; 17 | } 18 | } 19 | return; 20 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/repl.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var vm, nodeREPL, jisp, replDefaults, start; 3 | vm = require("vm"); 4 | nodeREPL = require("repl"); 5 | jisp = require("./jisp"); 6 | replDefaults = { 7 | useGlobal: true, 8 | prompt: "jisp> ", 9 | eval: (function(input, context, filename, cb) { 10 | var js, result, _ref; 11 | input = input.replace(/\uFF00/g, "\n"); 12 | input = input.replace(/^\(([^]*)\n\)$/g, "$1"); 13 | try { 14 | js = jisp.compile(input, { 15 | wrap: false, 16 | repl: true 17 | }); 18 | console.log("-- compiled:"); 19 | console.log(js); 20 | console.log("-- executing:"); 21 | result = vm.runInThisContext(js, filename); 22 | _ref = cb(null, result); 23 | } catch (err) { 24 | _ref = cb(err); 25 | } 26 | return _ref; 27 | }) 28 | }; 29 | 30 | function enableMultiline(repl) { 31 | var rli, inputStream, outputStream, origPrompt, multiline, lineListener; 32 | rli = repl.rli; 33 | inputStream = repl.inputStream; 34 | outputStream = repl.outputStream; 35 | origPrompt = (((typeof repl !== 'undefined') && (typeof repl._prompt !== 'undefined')) ? repl._prompt : repl.prompt); 36 | multiline = { 37 | enabled: false, 38 | prompt: origPrompt.replace(/^[^>\s]*>?/, (function(x) { 39 | return x.replace(/./g, "."); 40 | })), 41 | buffer: "" 42 | }; 43 | lineListener = rli.listeners("line")[0]; 44 | rli.removeListener("line", lineListener); 45 | return rli.on("line", (function(cmd) { 46 | var m, opened, closed, _ref, _ref0, _ref1; 47 | if (multiline.enabled) { 48 | multiline.buffer += (cmd + "\n"); 49 | opened = ((typeof(m = multiline.buffer.match(/\(/g)) !== 'undefined') ? m.length : 0); 50 | closed = ((typeof(m = multiline.buffer.match(/\)/g)) !== 'undefined') ? m.length : 0); 51 | if ((opened > closed)) { 52 | rli.setPrompt(multiline.prompt); 53 | _ref = rli.prompt(true); 54 | } else { 55 | multiline.enabled = false; 56 | multiline.buffer = multiline.buffer.replace(/\n/g, "\uFF00"); 57 | rli.emit("line", multiline.buffer); 58 | multiline.buffer = ""; 59 | rli.setPrompt(origPrompt); 60 | _ref = rli.prompt(true); 61 | } 62 | _ref1 = _ref; 63 | } else { 64 | opened = ((typeof(m = cmd.match(/\(/g)) === "string") ? m.length : 0); 65 | closed = ((typeof(m = cmd.match(/\)/g)) === "string") ? m.length : 0); 66 | if ((opened > closed)) { 67 | multiline.enabled = true; 68 | multiline.buffer += (cmd + "\n"); 69 | rli.setPrompt(multiline.prompt); 70 | _ref0 = rli.prompt(true); 71 | } else { 72 | _ref0 = lineListener(cmd); 73 | } 74 | _ref1 = _ref0; 75 | } 76 | return _ref1; 77 | })); 78 | } 79 | enableMultiline; 80 | return exports.start = (start = (function() { 81 | var repl; 82 | repl = nodeREPL.start(replDefaults); 83 | repl.on("exit", (function() { 84 | return repl.outputStream.write("\n"); 85 | })); 86 | enableMultiline(repl); 87 | return repl; 88 | })); 89 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/tokenise.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var tokens, recode, recomment, redstring, resstring, rereg; 3 | tokens = []; 4 | recode = /^[^]*?(?=;.*[\n\r]?|""|"[^]*?(?:[^\\]")|''|'[^]*?(?:[^\\]')|\/[^\s]+\/[\w]*)/; 5 | recomment = /^;.*[\n\r]?/; 6 | redstring = /^""|^"[^]*?(?:[^\\]")[^\s):\[\]\{\}]*/; 7 | resstring = /^''|^'[^]*?(?:[^\\]')[^\s):\[\]\{\}]*/; 8 | rereg = /^\/[^\s]+\/[\w]*[^\s)]*/; 9 | 10 | function grate(str) { 11 | return str 12 | .replace(/;.*$/gm, "") 13 | .replace(/\{/g, "(fn (") 14 | .replace(/\}/g, "))") 15 | .replace(/\(/g, " ( ") 16 | .replace(/\)/g, " ) ") 17 | .replace(/\[$/g, " [ ") 18 | .replace(/\['/g, " [ '") 19 | .replace(/\["/g, ' [ "') 20 | .replace(/'\]/g, "' ] ") 21 | .replace(/"\]/g, '" ] ') 22 | .replace(/\[[\s]*\(/g, " [ ( ") 23 | .replace(/\)[\s]*\]/g, " ) ] ") 24 | .replace(/([^:]):(?!\:)/g, "$1 : ") 25 | .replace(/`/g, " ` ") 26 | .replace(/,/g, " , ") 27 | .replace(/\.\.\./g, " ... ") 28 | .replace(/…/g, " … ") 29 | .trim() 30 | .split(/\s+/); 31 | } 32 | grate; 33 | 34 | function concatNewLines(str) { 35 | return str.replace(/\n|\n\r/g, "\\n"); 36 | } 37 | concatNewLines; 38 | 39 | function match(str, re) { 40 | var mask; 41 | return (((mask = str.match(re)) && (mask[0].length > 0)) ? mask[0] : null); 42 | } 43 | match; 44 | 45 | function tokenise(str) { 46 | var mask; 47 | tokens = []; 48 | while ((str = str.trim()).length > 0) { 49 | if ((mask = match(str, recode))) { 50 | tokens.push.apply(tokens, [].concat(grate(mask))); 51 | str = str.replace(recode, ""); 52 | } else if (mask = match(str, recomment)) { 53 | str = str.replace(recomment, ""); 54 | } else if (mask = match(str, redstring)) { 55 | tokens.push(concatNewLines(mask)); 56 | str = str.replace(redstring, ""); 57 | } else if (mask = match(str, resstring)) { 58 | tokens.push(concatNewLines(mask)); 59 | str = str.replace(resstring, ""); 60 | } else if (mask = match(str, rereg)) { 61 | tokens.push(mask); 62 | str = str.replace(rereg, ""); 63 | } else { 64 | tokens.push.apply(tokens, [].concat(grate(str))); 65 | str = ""; 66 | } 67 | } 68 | return tokens.filter((function(x) { 69 | return ((typeof x !== 'undefined') && (x !== "" && x !== undefined && x !== null)); 70 | })); 71 | } 72 | tokenise; 73 | return module.exports = tokenise; 74 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/uniq.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var utils; 3 | utils = require("./utils"); 4 | 5 | function Uniq(uniq, store) { 6 | var of, name, _ref; 7 | this.parent = uniq; 8 | this.store = {}; 9 | if (store) { 10 | _ref = store; 11 | for (of in _ref) { 12 | name = _ref[of]; 13 | this.store[of] = name; 14 | } 15 | } 16 | return this; 17 | } 18 | Uniq; 19 | Uniq.prototype.find = (function(func) { 20 | var uniq, ref, _ref; 21 | uniq = this; 22 | while (typeof uniq !== 'undefined') { 23 | if ((ref = func.call(uniq))) { 24 | _ref = undefined; 25 | break; 26 | } else { 27 | _ref = (uniq = uniq.parent); 28 | } 29 | _ref; 30 | } 31 | return ref; 32 | }); 33 | Uniq.prototype.findOut = (function(func) { 34 | return (((typeof this !== 'undefined') && (typeof this.parent !== 'undefined')) ? this.parent.find(func) : undefined); 35 | }); 36 | Uniq.prototype.has = (function(key) { 37 | return ([].indexOf.call(Object.keys(this.store), key) >= 0); 38 | }); 39 | Uniq.prototype.conflict = (function(key) { 40 | return this.findOut((function() { 41 | return this.has(key); 42 | })); 43 | }); 44 | Uniq.prototype.resolve = (function(key) { 45 | var oldkey; 46 | oldkey = key; 47 | while (this.conflict(key)) { 48 | key = utils.plusname(key); 49 | } 50 | return (this.store[key] = (this.store[oldkey] = (function(name) { 51 | return name.replace(RegExp("^" + oldkey), key); 52 | }))); 53 | }); 54 | Uniq.prototype.checkAndReplace = (function(name) { 55 | var key; 56 | key = utils.getServicePart(name); 57 | if (!this.has(key)) this.resolve(key); 58 | return this.store[key](name); 59 | }); 60 | return module.exports = Uniq; 61 | })['call'](this); -------------------------------------------------------------------------------- /dev/jisp/util.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var keywords, specialValues; 3 | exports.keywords = (keywords = ["return", "break", "continue", "throw", "delete"]); 4 | 5 | function kwtest(str) { 6 | var kw, re, _i, _res, _ref, _ref0; 7 | _res = []; 8 | _ref = keywords; 9 | for (_i = 0; _i < _ref.length; ++_i) { 10 | kw = _ref[_i]; 11 | if (typeof(_ref0 = ("^" + kw + " |^" + kw + "$")) !== 'undefined') _res.push(_ref0); 12 | } 13 | re = RegExp(_res 14 | .join("|")); 15 | return re.test(str); 16 | } 17 | exports.kwtest = kwtest; 18 | exports.specialValues = (specialValues = ["undefined", "null", "true", "false", "yes", "no", "Infinity", "NaN"]); 19 | 20 | function isSpecialValueStr(str) { 21 | return ([].indexOf.call(specialValues, str) >= 0); 22 | } 23 | exports.isSpecialValueStr = isSpecialValueStr; 24 | 25 | function isSpecialValue(form) { 26 | return ((typeof form === "undefined") || (form === null) || ((typeof form === "number") && isNaN(form)) || (form === Infinity) || (typeof form === "boolean")); 27 | } 28 | exports.isSpecialValue = isSpecialValue; 29 | 30 | function isAtom(form) { 31 | return ((form === undefined || form === null) || /^\/[^\s\/]+\/[\w]*$/.test(form) || (typeof form === "number" || typeof form === "string" || typeof form === "boolean")); 32 | } 33 | exports.isAtom = isAtom; 34 | 35 | function isaString(form) { 36 | return (typeof form === "string"); 37 | } 38 | exports.isaString = isaString; 39 | 40 | function isList(form) { 41 | return Array.isArray(form); 42 | } 43 | exports.isList = isList; 44 | 45 | function isHash(form) { 46 | return (!isAtom(form) && !isList(form) && !(typeof form === "function")); 47 | } 48 | exports.isHash = isHash; 49 | 50 | function isBlankObject(form) { 51 | var _ref, _err; 52 | try { 53 | _ref = Object.keys(form).length === 0; 54 | } catch (_err) { 55 | _ref = false; 56 | } 57 | return _ref; 58 | } 59 | exports.isBlankObject = isBlankObject; 60 | 61 | function isKey(form) { 62 | return (isAtom(form) && (isString(form) || isIdentifier(form) || isNum(form))); 63 | } 64 | exports.isKey = isKey; 65 | 66 | function isVarName(form) { 67 | return (isAtom(form) && /^[$_A-Za-z]{1}$|^[$_A-Za-z]+[$_\w]*(?:[$_\w](?!\.))+$/.test(form)); 68 | } 69 | exports.isVarName = isVarName; 70 | 71 | function isIdentifier(form) { 72 | return (isAtom(form) && /^[$_A-Za-z]{1}[$_\w]*((\.[$_A-Za-z]{1}[$_\w]*)|(\[[$_.\w\[\]]+\])|(\['.*'\])|(\[".*"\]))*$/.test(form)); 73 | } 74 | exports.isIdentifier = isIdentifier; 75 | 76 | function isString(form) { 77 | return (isAtom(form) && /^".*"$|^'.*'$/.test(form)); 78 | } 79 | exports.isString = isString; 80 | 81 | function isRegex(form) { 82 | return (isAtom(form) && /^\/[^\s]+\/[\w]*[^\s)]*/.test(form)); 83 | } 84 | exports.isRegex = isRegex; 85 | 86 | function isNum(form) { 87 | return (isAtom(form) && (typeof typify(form) === "number")); 88 | } 89 | exports.isNum = isNum; 90 | 91 | function isPrimitive(form) { 92 | return (isRegex(form) || isNum(form) || (form === undefined || form === null || form === true || form === false)); 93 | } 94 | exports.isPrimitive = isPrimitive; 95 | 96 | function isArgHash(form) { 97 | return (isAtom(form) && /^#[\d]+$/.test(form)); 98 | } 99 | exports.isArgHash = isArgHash; 100 | 101 | function isArgsHash(form) { 102 | return (isAtom(form) && /^#$/.test(form)); 103 | } 104 | exports.isArgsHash = isArgsHash; 105 | 106 | function isArgHashNotation(form) { 107 | return (isArgHash(form) || isArgsHash(form)); 108 | } 109 | exports.isArgHashNotation = isArgHashNotation; 110 | 111 | function isDotName(form) { 112 | return (isAtom(form) && /^\.[$_A-Za-z]{1}$|^\.[$_A-Za-z]+[$_.\w]*(?:[$_\w](?!\.))+$/.test(form)); 113 | } 114 | exports.isDotName = isDotName; 115 | 116 | function isBracketName(form) { 117 | return (isAtom(form) && /^\[[$_A-Za-z]{1}\]$|^\[[$_A-Za-z]+[$_.\w]*(?:[$_\w](?!\.))+\]$/.test(form)); 118 | } 119 | exports.isBracketName = isBracketName; 120 | 121 | function isBracketString(form) { 122 | return (isAtom(form) && /^\[".*"\]$|^\['.*'\]$/.test(form)); 123 | } 124 | exports.isBracketString = isBracketString; 125 | 126 | function isPropSyntax(form) { 127 | return (isAtom(form) && (isDotName(form) || isBracketName(form) || isBracketString(form))); 128 | } 129 | exports.isPropSyntax = isPropSyntax; 130 | 131 | function typify(form) { 132 | var _ref; 133 | if (!isAtom(form)) { 134 | _ref = undefined; 135 | throw Error("expecting atom, got " + pr(form)); 136 | } else if (isBlankObject(form)) { 137 | _ref = form; 138 | } else if (typeof form === "undefined") { 139 | _ref = undefined; 140 | } else if (form === "null") { 141 | _ref = null; 142 | } else if (form === "true" || form === "yes") { 143 | _ref = true; 144 | } else if (form === "false" || form === "no") { 145 | _ref = false; 146 | } else if (!isNaN(Number(form))) { 147 | _ref = Number(form); 148 | } else if (isRegex(form)) { 149 | _ref = form; 150 | } else if (typeof form === "string") { 151 | _ref = form; 152 | } else { 153 | _ref = undefined; 154 | throw Error("syntax error: unrecognised type of " + pr(form)); 155 | } 156 | return _ref; 157 | } 158 | exports.typify = typify; 159 | 160 | function assertForm(form, min, max, first) { 161 | var _ref; 162 | if ((typeof min === 'undefined')) min = 0; 163 | if ((typeof max === 'undefined')) max = Infinity; 164 | if (!isList(form)) { 165 | _ref = undefined; 166 | throw Error("expecting list, got " + form); 167 | } else if (!((form.length >= min) && (form.length <= max))) { 168 | _ref = undefined; 169 | throw Error("expecting between " + min + " and " + max + " arguments, got " + form.length + ": " + pr(form)); 170 | } else if ((typeof first !== 'undefined') && (form[0] !== first)) { 171 | _ref = undefined; 172 | throw Error("expecting " + pr(first) + " as first element, got " + pr(form[0])); 173 | } else { 174 | _ref = form; 175 | } 176 | return _ref; 177 | } 178 | exports.assertForm = assertForm; 179 | 180 | function assertExp(exp, test, expect) { 181 | var _ref; 182 | if ((typeof expect === 'undefined')) expect = "valid expression"; 183 | if (test(exp)) { 184 | _ref = true; 185 | } else { 186 | _ref = undefined; 187 | throw Error("expecting " + pr(expect) + ", got " + pr(exp)); 188 | } 189 | return _ref; 190 | } 191 | exports.assertExp = assertExp; 192 | 193 | function splitName(name) { 194 | var re, reDot, reBracket, reBracketGreedy, res, reg; 195 | re = /\.[$_\w]+$|\[[^\[\]]+\]$|\[.+\]$/; 196 | reDot = /\.[$_\w]+$/; 197 | reBracket = /\[[^\[\]]+\]$/; 198 | reBracketGreedy = /\[.+\]$/; 199 | res = []; 200 | while (name.match(re)) { 201 | reg = (name.match(reDot) && reDot) || (name.match(reBracket) && reBracket) || (name.match(reBracketGreedy) && reBracketGreedy); 202 | res.unshift(name.match(reg)[0]); 203 | name = name.replace(reg, ""); 204 | } 205 | res.unshift(name); 206 | return res; 207 | } 208 | exports.splitName = splitName; 209 | 210 | function pr(item) { 211 | var res, key, val, _ref, _ref0, _i, _ref1; 212 | if (isAtom(item)) { 213 | _ref = ("" + item) 214 | .replace(/;$/, ""); 215 | } else if (isHash(item)) { 216 | res = ""; 217 | _ref0 = item; 218 | for (key in _ref0) { 219 | val = _ref0[key]; 220 | res += (key + ": " + pr(val) + ", "); 221 | } 222 | _ref = ("{ " + res.slice(0, -2) + " }"); 223 | } else if (isList(item)) { 224 | res = ""; 225 | _ref1 = item; 226 | for (_i = 0; _i < _ref1.length; ++_i) { 227 | val = _ref1[_i]; 228 | res += (pr(val) + ", "); 229 | } 230 | _ref = ("[ " + res.slice(0, -2) + " ]"); 231 | } else { 232 | _ref = ("" + item); 233 | } 234 | return _ref; 235 | } 236 | exports.pr = pr; 237 | 238 | function spr(item) { 239 | var res, val, _i, _ref, _ref0; 240 | if (isList(item)) { 241 | res = ""; 242 | _ref = item; 243 | for (_i = 0; _i < _ref.length; ++_i) { 244 | val = _ref[_i]; 245 | res += (pr(val) + ", "); 246 | } 247 | _ref0 = res.slice(0, res.length - 2); 248 | } else { 249 | _ref0 = undefined; 250 | throw Error("can only print-spread lists"); 251 | } 252 | return _ref0; 253 | } 254 | exports.spr = spr; 255 | 256 | function render(buffer) { 257 | var i, exp, res, _ref; 258 | _ref = buffer; 259 | for (i = 0; i < _ref.length; ++i) { 260 | exp = _ref[i]; 261 | if (((isList(exp) && (exp.length === 0)) || (typeof exp === "undefined") || (exp === ""))) { 262 | buffer[i] = undefined; 263 | } else { 264 | res = ((typeof exp === "string") ? exp.trim() : pr(exp)); 265 | if ((isHash(exp) || /^function\s*\(/.test(res))) res = "(" + res + ")"; 266 | if (!/:$|\}$|;$/.test(res.slice(-1))) res += ";"; 267 | buffer[i] = res; 268 | } 269 | } 270 | return buffer.join(" ") 271 | .trim(); 272 | } 273 | exports.render = render; 274 | 275 | function deParenthesise(str) { 276 | var _ref; 277 | if ((typeof str === "string")) { 278 | while (str.match(/^\({1}/) && str.match(/\){1}$/)) { 279 | (str = str 280 | .replace(/^\({1}/, "") 281 | .replace(/\){1}$/, "")); 282 | } 283 | _ref = str; 284 | } else { 285 | _ref = str; 286 | } 287 | return _ref; 288 | } 289 | exports.deParenthesise = deParenthesise; 290 | 291 | function dePairParenthesise(str) { 292 | var _ref; 293 | if ((typeof str === "string")) { 294 | while (str.match(/^\({2}/) && str.match(/\){2}$/)) { 295 | (str = str 296 | .replace(/^\({2}/, "(") 297 | .replace(/\){2}$/, ")")); 298 | } 299 | _ref = str; 300 | } else { 301 | _ref = str; 302 | } 303 | return _ref; 304 | } 305 | exports.dePairParenthesise = dePairParenthesise; 306 | 307 | function merge(options, overrides) { 308 | return extend(extend({}, options), overrides); 309 | } 310 | exports.merge = merge; 311 | 312 | function extend(object, properties) { 313 | var key, val, _ref; 314 | _ref = properties; 315 | for (key in _ref) { 316 | val = _ref[key]; 317 | object[key] = val; 318 | } 319 | return object; 320 | } 321 | exports.extend = extend; 322 | 323 | function baseFileName(file, stripExt, useWinPathSep) { 324 | var pathSep, parts; 325 | if ((typeof stripExt === 'undefined')) stripExt = false; 326 | if ((typeof useWinPathSep === 'undefined')) useWinPathSep = false; 327 | pathSep = (useWinPathSep ? /\\|\// : /\//); 328 | parts = file.split(pathSep); 329 | file = parts.slice(-1)[0]; 330 | if (!(stripExt && (file.indexOf(".") >= 0))) return file; 331 | parts = file.split("."); 332 | parts.pop(); 333 | if (((parts.slice(-1)[0] === "jisp") && (parts.length > 1))) parts.pop(); 334 | return parts.join("."); 335 | } 336 | exports.baseFileName = baseFileName; 337 | 338 | function repeat(str, n) { 339 | var res; 340 | res = ""; 341 | while (n > 0) { 342 | if ((n & 1)) res += str; 343 | n >>>= 1; 344 | str += str; 345 | } 346 | return res; 347 | } 348 | exports.repeat = repeat; 349 | 350 | function isJisp(file) { 351 | return /\.jisp$/.test(file); 352 | } 353 | return exports.isJisp = isJisp; 354 | }).call(this); -------------------------------------------------------------------------------- /dev/jisp/utils.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var keywords, specialValues; 3 | exports.keywords = (keywords = ["return", "break", "continue", "throw", "delete"]); 4 | 5 | function kwtest(str) { 6 | var kw, re, _i, _res, _ref, _ref0; 7 | _res = []; 8 | _ref = keywords; 9 | for (_i = 0; _i < _ref.length; ++_i) { 10 | kw = _ref[_i]; 11 | if (typeof(_ref0 = ("^" + kw + " |^" + kw + "$")) !== 'undefined') _res.push(_ref0); 12 | } 13 | re = RegExp(_res 14 | .join("|")); 15 | return re.test(str); 16 | } 17 | exports.kwtest = kwtest; 18 | exports.specialValues = (specialValues = ["undefined", "null", "true", "false", "yes", "no", "Infinity", "NaN", "this"]); 19 | 20 | function isSpecialValueStr(str) { 21 | return ([].indexOf.call(specialValues, str) >= 0); 22 | } 23 | exports.isSpecialValueStr = isSpecialValueStr; 24 | 25 | function isSpecialValue(form) { 26 | return ((typeof form === "undefined") || (form === null) || ((typeof form === "number") && isNaN(form)) || (form === Infinity) || (typeof form === "boolean")); 27 | } 28 | exports.isSpecialValue = isSpecialValue; 29 | 30 | function isAtom(form) { 31 | return ((form === undefined || form === null) || /^\/[^\s\/]+\/[\w]*$/.test(form) || (typeof form === "number" || typeof form === "string" || typeof form === "boolean")); 32 | } 33 | exports.isAtom = isAtom; 34 | 35 | function isaString(form) { 36 | return (typeof form === "string"); 37 | } 38 | exports.isaString = isaString; 39 | 40 | function isList(form) { 41 | return Array.isArray(form); 42 | } 43 | exports.isList = isList; 44 | 45 | function isHash(form) { 46 | return (!isAtom(form) && !isList(form) && !(typeof form === "function")); 47 | } 48 | exports.isHash = isHash; 49 | 50 | function isBlankObject(form) { 51 | var _ref, _err; 52 | try { 53 | _ref = Object.keys(form).length === 0; 54 | } catch (_err) { 55 | _ref = false; 56 | } 57 | return _ref; 58 | } 59 | exports.isBlankObject = isBlankObject; 60 | 61 | function isKey(form) { 62 | return (isAtom(form) && (isString(form) || isIdentifier(form) || isNum(form))); 63 | } 64 | exports.isKey = isKey; 65 | 66 | function isServiceName(form) { 67 | return ((typeof form === "string") && /^#/.test(form) && !/^#$|^#\d|^#\.|^#\[/.test(form)); 68 | } 69 | exports.isService = isServiceName; 70 | 71 | function getServicePart(form) { 72 | return form.match(/^#[^.[]+/)[0]; 73 | } 74 | exports.getServicePart = getServicePart; 75 | 76 | function isVarName(form) { 77 | return (isAtom(form) && /^[$#_A-Za-z]{1}$|^[$#_A-Za-z]+[$_\w]*(?:[$_\w](?!\.))+$/.test(form)); 78 | } 79 | exports.isVarName = isVarName; 80 | 81 | function isIdentifier(form) { 82 | return (isAtom(form) && /^[$#_A-Za-z]{1}[$_\w()]*((\.[$#_A-Za-z]{1}[$_\w()]*)|(\[[$_.\w()\[\]]+\])|(\['.*'\])|(\[".*"\]))*$/.test(form)); 83 | } 84 | exports.isIdentifier = isIdentifier; 85 | 86 | function isString(form) { 87 | return (isAtom(form) && /^".*"$|^'.*'$/.test(form)); 88 | } 89 | exports.isString = isString; 90 | 91 | function isRegex(form) { 92 | return (isAtom(form) && /^\/[^\s]+\/[\w]*[^\s)]*/.test(form)); 93 | } 94 | exports.isRegex = isRegex; 95 | 96 | function isNum(form) { 97 | return (isAtom(form) && (typeof typify(form) === "number")); 98 | } 99 | exports.isNum = isNum; 100 | 101 | function isPrimitive(form) { 102 | return (isRegex(form) || isNum(form) || (form === undefined || form === null || form === true || form === false)); 103 | } 104 | exports.isPrimitive = isPrimitive; 105 | 106 | function isArgHash(form) { 107 | return (isAtom(form) && /^#[\d]+$/.test(form)); 108 | } 109 | exports.isArgHash = isArgHash; 110 | 111 | function isArgsHash(form) { 112 | return (isAtom(form) && /^#$/.test(form)); 113 | } 114 | exports.isArgsHash = isArgsHash; 115 | 116 | function isArgHashNotation(form) { 117 | return (isArgHash(form) || isArgsHash(form)); 118 | } 119 | exports.isArgHashNotation = isArgHashNotation; 120 | 121 | function isDotName(form) { 122 | return (isAtom(form) && /^\.[$#_A-Za-z]{1}$|^\.[$#_A-Za-z]+[$_.\w]*(?:[$_\w](?!\.))+$/.test(form)); 123 | } 124 | exports.isDotName = isDotName; 125 | 126 | function isBracketName(form) { 127 | return (isAtom(form) && (/^\[[$#_A-Za-z]{1}\]$|^\[[$#_A-Za-z]+[$_.\w()]*(?:[$_\w()](?!\.))+\]$/.test(form) || /^\[[\d]+\]/.test(form))); 128 | } 129 | exports.isBracketName = isBracketName; 130 | 131 | function isBracketString(form) { 132 | return (isAtom(form) && /^\[".*"\]$|^\['.*'\]$/.test(form)); 133 | } 134 | exports.isBracketString = isBracketString; 135 | 136 | function isPropSyntax(form) { 137 | return (isAtom(form) && (isDotName(form) || isBracketName(form) || isBracketString(form))); 138 | } 139 | exports.isPropSyntax = isPropSyntax; 140 | 141 | function typify(form) { 142 | var _ref; 143 | if (!isAtom(form)) { 144 | _ref = undefined; 145 | throw Error("expecting atom, got " + pr(form)); 146 | } else if (isBlankObject(form)) { 147 | _ref = form; 148 | } else if (typeof form === "undefined") { 149 | _ref = undefined; 150 | } else if (form === "null") { 151 | _ref = null; 152 | } else if (form === "true" || form === "yes") { 153 | _ref = true; 154 | } else if (form === "false" || form === "no") { 155 | _ref = false; 156 | } else if (!isNaN(Number(form))) { 157 | _ref = Number(form); 158 | } else if (isRegex(form)) { 159 | _ref = form; 160 | } else if (typeof form === "string") { 161 | _ref = form; 162 | } else { 163 | _ref = undefined; 164 | throw Error("syntax error: unrecognised type of " + pr(form)); 165 | } 166 | return _ref; 167 | } 168 | exports.typify = typify; 169 | 170 | function assertForm(form, min, max, first) { 171 | var _ref; 172 | if ((typeof min === 'undefined')) min = 0; 173 | if ((typeof max === 'undefined')) max = Infinity; 174 | if (!isList(form)) { 175 | _ref = undefined; 176 | throw Error("expecting list, got " + form); 177 | } else if (!((form.length >= min) && (form.length <= max))) { 178 | _ref = undefined; 179 | throw Error("expecting between " + min + " and " + max + " arguments, got " + form.length + ": " + pr(form)); 180 | } else if ((typeof first !== 'undefined') && (form[0] !== first)) { 181 | _ref = undefined; 182 | throw Error("expecting " + pr(first) + " as first element, got " + pr(form[0])); 183 | } else { 184 | _ref = form; 185 | } 186 | return _ref; 187 | } 188 | exports.assertForm = assertForm; 189 | 190 | function assertExp(exp, test, expect) { 191 | var _ref; 192 | if ((typeof expect === 'undefined')) expect = "valid expression"; 193 | if (test(exp)) { 194 | _ref = true; 195 | } else { 196 | _ref = undefined; 197 | throw Error("expecting " + pr(expect) + ", got " + pr(exp)); 198 | } 199 | return _ref; 200 | } 201 | exports.assertExp = assertExp; 202 | 203 | function splitName(name) { 204 | var re, reDot, reBracket, reBracketGreedy, res, reg; 205 | re = /\.[$_\w]+$|\[[^\[\]]+\]$|\[.+\]$/; 206 | reDot = /\.[$_\w]+$/; 207 | reBracket = /\[[^\[\]]+\]$/; 208 | reBracketGreedy = /\[.+\]$/; 209 | res = []; 210 | while (name.match(re)) { 211 | reg = (name.match(reDot) && reDot) || (name.match(reBracket) && reBracket) || (name.match(reBracketGreedy) && reBracketGreedy); 212 | res.unshift(name.match(reg)[0]); 213 | name = name.replace(reg, ""); 214 | } 215 | res.unshift(name); 216 | return res; 217 | } 218 | exports.splitName = splitName; 219 | 220 | function plusname(name) { 221 | return (isNaN(Number(name["slice"](-1)[0])) ? (name + 0) : (name["slice"](0, -1) + (1 + Number(name["slice"](-1)[0])))); 222 | } 223 | exports.plusname = plusname; 224 | 225 | function pr(item) { 226 | var res, key, val, _ref, _ref0, _i, _ref1; 227 | if (isAtom(item)) { 228 | _ref = ("" + item) 229 | .replace(/;$/, ""); 230 | } else if (isHash(item)) { 231 | res = ""; 232 | _ref0 = item; 233 | for (key in _ref0) { 234 | val = _ref0[key]; 235 | res += (key + ": " + pr(val) + ", "); 236 | } 237 | _ref = ("{ " + res.slice(0, -2) + " }"); 238 | } else if (isList(item)) { 239 | res = ""; 240 | _ref1 = item; 241 | for (_i = 0; _i < _ref1.length; ++_i) { 242 | val = _ref1[_i]; 243 | res += (pr(val) + ", "); 244 | } 245 | _ref = ("[ " + res.slice(0, -2) + " ]"); 246 | } else { 247 | _ref = ("" + item); 248 | } 249 | return _ref; 250 | } 251 | exports.pr = pr; 252 | 253 | function spr(item) { 254 | var res, val, _i, _ref, _ref0; 255 | if (isList(item)) { 256 | res = ""; 257 | _ref = item; 258 | for (_i = 0; _i < _ref.length; ++_i) { 259 | val = _ref[_i]; 260 | res += (pr(val) + ", "); 261 | } 262 | _ref0 = res.slice(0, res.length - 2); 263 | } else { 264 | _ref0 = undefined; 265 | throw Error("can only print-spread lists"); 266 | } 267 | return _ref0; 268 | } 269 | exports.spr = spr; 270 | 271 | function render(buffer) { 272 | var i, exp, res, _ref; 273 | _ref = buffer; 274 | for (i = 0; i < _ref.length; ++i) { 275 | exp = _ref[i]; 276 | if (((isList(exp) && (exp.length === 0)) || (typeof exp === "undefined") || (exp === ""))) { 277 | buffer[i] = undefined; 278 | } else { 279 | res = ((typeof exp === "string") ? exp.trim() : pr(exp)); 280 | if ((isHash(exp) || /^function\s*\(/.test(res))) res = "(" + res + ")"; 281 | if (!/:$|\}$|;$/.test(res.slice(-1))) res += ";"; 282 | buffer[i] = res; 283 | } 284 | } 285 | return buffer.join(" ") 286 | .trim(); 287 | } 288 | exports.render = render; 289 | 290 | function deParenthesise(str) { 291 | var _ref; 292 | if ((typeof str === "string")) { 293 | while (str.match(/^\({1}/) && str.match(/\){1}$/)) { 294 | (str = str 295 | .replace(/^\({1}/, "") 296 | .replace(/\){1}$/, "")); 297 | } 298 | _ref = str; 299 | } else { 300 | _ref = str; 301 | } 302 | return _ref; 303 | } 304 | exports.deParenthesise = deParenthesise; 305 | 306 | function dePairParenthesise(str) { 307 | var _ref; 308 | if ((typeof str === "string")) { 309 | while (str.match(/^\({2}/) && str.match(/\){2}$/)) { 310 | (str = str 311 | .replace(/^\({2}/, "(") 312 | .replace(/\){2}$/, ")")); 313 | } 314 | _ref = str; 315 | } else { 316 | _ref = str; 317 | } 318 | return _ref; 319 | } 320 | exports.dePairParenthesise = dePairParenthesise; 321 | 322 | function merge(options, overrides) { 323 | return extend(extend({}, options), overrides); 324 | } 325 | exports.merge = merge; 326 | 327 | function extend(object, properties) { 328 | var key, val, _ref; 329 | _ref = properties; 330 | for (key in _ref) { 331 | val = _ref[key]; 332 | object[key] = val; 333 | } 334 | return object; 335 | } 336 | exports.extend = extend; 337 | 338 | function baseFileName(file, stripExt, useWinPathSep) { 339 | var pathSep, parts; 340 | if ((typeof stripExt === 'undefined')) stripExt = false; 341 | if ((typeof useWinPathSep === 'undefined')) useWinPathSep = false; 342 | pathSep = (useWinPathSep ? /\\|\// : /\//); 343 | parts = file.split(pathSep); 344 | file = parts["slice"](-1)[0]; 345 | if (!(stripExt && (file.indexOf(".") >= 0))) return file; 346 | parts = file.split("."); 347 | parts.pop(); 348 | if (((parts["slice"](-1)[0] === "jisp") && (parts.length > 1))) parts.pop(); 349 | return parts.join("."); 350 | } 351 | exports.baseFileName = baseFileName; 352 | 353 | function repeat(str, n) { 354 | var res; 355 | res = ""; 356 | while (n > 0) { 357 | if ((n & 1)) res += str; 358 | n >>>= 1; 359 | str += str; 360 | } 361 | return res; 362 | } 363 | exports.repeat = repeat; 364 | 365 | function isJisp(file) { 366 | return /\.jisp$/.test(file); 367 | } 368 | return exports.isJisp = isJisp; 369 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/browser.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var jisp, compile; 3 | jisp = require("./jisp"); 4 | jisp.require = require; 5 | compile = jisp.compile; 6 | jisp.eval = (function(code, options) { 7 | if ((typeof options === 'undefined')) options = {}; 8 | options.wrap = false; 9 | return eval(compile(code, options)); 10 | }); 11 | jisp.run = (function(code, options) { 12 | var compiled; 13 | if ((typeof options === 'undefined')) options = {}; 14 | options.wrap = false; 15 | compiled = compile(code, options); 16 | return Function(compile(code, options))(); 17 | }); 18 | if ((typeof window === 'undefined')) return; 19 | jisp.load = (function(url, callback, options, hold) { 20 | var xhr; 21 | if ((typeof options === 'undefined')) options = {}; 22 | if ((typeof hold === 'undefined')) hold = false; 23 | options.sourceFiles = [url]; 24 | xhr = (window.ActiveXObject ? new window.ActiveXObject("Microsoft.XMLHTTP") : new window.XMLHttpRequest()); 25 | xhr.open("GET", url, true); 26 | if (("overrideMimeType" in xhr)) xhr.overrideMimeType("text/plain"); 27 | xhr.onreadystatechange = (function() { 28 | var param; 29 | if ((xhr.readyState === 4)) { 30 | if ((xhr.status === 0 || xhr.status === 200)) { 31 | param = [xhr.responseText, options]; 32 | if (!hold) jisp.run.apply(jisp, [].concat(param)); 33 | } else { 34 | throw new Error(("Could not load " + url)); 35 | } 36 | } 37 | return (callback ? callback(param) : undefined); 38 | }); 39 | return xhr.send(null); 40 | }); 41 | 42 | function runScripts() { 43 | var scripts, jisps, index, s, i, script, _i, _ref, _ref0; 44 | scripts = window.document.getElementsByTagName("script"); 45 | jisps = []; 46 | index = 0; 47 | _ref = scripts; 48 | for (_i = 0; _i < _ref.length; ++_i) { 49 | s = _ref[_i]; 50 | if ((s.type === "text/jisp")) jisps.push(s); 51 | } 52 | 53 | function execute() { 54 | var param, _ref0; 55 | param = jisps[index]; 56 | if ((param instanceof Array)) { 57 | jisp.run.apply(jisp, [].concat(param)); 58 | ++index; 59 | _ref0 = execute(); 60 | } else { 61 | _ref0 = undefined; 62 | } 63 | return _ref0; 64 | } 65 | execute; 66 | _ref0 = jisps; 67 | for (i = 0; i < _ref0.length; ++i) { 68 | script = _ref0[i]; 69 | (function(script, i) { 70 | var options, _ref1; 71 | options = {}; 72 | if (script.src) { 73 | _ref1 = jisp.load(script.src, (function(param) { 74 | jisps[i] = param; 75 | return execute(); 76 | }), options, true); 77 | } else { 78 | options.sourceFiles = ["embedded"]; 79 | _ref1 = (jisps[i] = [script.innerHTML, options]); 80 | } 81 | return _ref1; 82 | })(script, i); 83 | } 84 | return execute(); 85 | } 86 | runScripts; 87 | return window.addEventListener ? window.addEventListener("DOMContentLoaded", runScripts, false) : window.attachEvent("onload", runScripts); 88 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/command.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var fs, path, mkdirp, spawn, exec, EventEmitter, jisp, utils, optparse, useWinPathSep, banner, switches, opts, sources, sourceCode, notSources, optionParser, joinTimeout, compileJoin; 3 | fs = require("fs"); 4 | path = require("path"); 5 | mkdirp = require("mkdirp"); 6 | spawn = require("child_process").spawn; 7 | exec = require("child_process").exec; 8 | EventEmitter = require("events").EventEmitter; 9 | jisp = require("./jisp"); 10 | utils = require("./utils"); 11 | optparse = require("./optparse"); 12 | useWinPathSep = path.sep === "\\ ".slice(0, 1); 13 | utils.extend(jisp, new EventEmitter()); 14 | 15 | function printLine(line) { 16 | return process.stdout.write(line + "\n"); 17 | } 18 | printLine; 19 | 20 | function printWarn(line) { 21 | return process.stderr.write(line + "\n"); 22 | } 23 | printWarn; 24 | 25 | function hidden(file) { 26 | return /^\.|~$/.test(file); 27 | } 28 | hidden; 29 | banner = "\nUsage: jisp [options] path/to/script.jisp -- [args]\n\nWhen called without options, compiles your script and prints the output to stdout."; 30 | switches = [ 31 | ["-c", "--compile", "compile to JavaScript and save as .js files"], 32 | ["-o", "--output [dir]", "set the output directory for compiled JavaScript"], 33 | ["-i", "--interactive", "run an interactive jisp REPL (this is the default with no options and arguments)"], 34 | ["-v", "--version", "display the version number"] 35 | ]; 36 | opts = {}; 37 | sources = []; 38 | sourceCode = []; 39 | notSources = {}; 40 | optionParser = null; 41 | 42 | function run() { 43 | var replCliOpts, literals, source, _i, _res, _ref, _ref0; 44 | parseOptions(); 45 | replCliOpts = { 46 | useGlobal: true 47 | }; 48 | if (opts.version) return version(); 49 | if ((opts.interactive || !opts.arguments.length)) return require("./repl").start(replCliOpts); 50 | literals = (opts.run ? opts.arguments.splice(1) : []); 51 | process.argv = process.argv.slice(0, 1).concat(literals); 52 | process.argv[0] = 'jisp'; 53 | if (opts.output) opts.output = path.resolve(opts.output); 54 | _res = []; 55 | _ref = opts.arguments; 56 | for (_i = 0; _i < _ref.length; ++_i) { 57 | source = _ref[_i]; 58 | source = path.resolve(source); 59 | if (typeof(_ref0 = compilePath(source, true, source)) !== 'undefined') _res.push(_ref0); 60 | } 61 | return _res; 62 | } 63 | exports.run = run; 64 | 65 | function compilePath(source, topLevel, base) { 66 | var stats, files, file, code, _i, _res, _ref, _ref0, _ref1, _ref2; 67 | if ((([].indexOf.call(sources, source) >= 0) || (!topLevel && (notSources[source] || hidden(source))))) undefined; 68 | try { 69 | stats = fs.statSync(source); 70 | } catch (err) { 71 | if ((err.code === "ENOENT")) { 72 | console.error("File not found:" + source); 73 | process.exit(1); 74 | } 75 | throw err; 76 | } 77 | if (stats.isDirectory()) { 78 | if ((path.basename(source) === "node_modules")) { 79 | _ref1 = (notSources[source] = true); 80 | } else if (opts.run) { 81 | _ref1 = compilePath(findDirectoryIndex(source), topLevel, base); 82 | } else { 83 | try { 84 | files = fs.readdirSync(source); 85 | } catch (err) { 86 | if ((err.code === "ENOENT")) {} else { 87 | throw err; 88 | } 89 | } 90 | _res = []; 91 | _ref = files; 92 | for (_i = 0; _i < _ref.length; ++_i) { 93 | file = _ref[_i]; 94 | if (typeof(_ref0 = compilePath(path.join(source, file), false, base)) !== 'undefined') _res.push(_ref0); 95 | } 96 | _ref1 = _res; 97 | } 98 | _ref2 = _ref1; 99 | } else if (topLevel || utils.isJisp(source)) { 100 | sources.push(source); 101 | sourceCode.push(null); 102 | delete notSources[source]; 103 | try { 104 | code = fs.readFileSync(source); 105 | } catch (err) { 106 | if ((err.code === "ENOENT")) { 107 | return; 108 | } else { 109 | throw err; 110 | } 111 | } 112 | _ref2 = compileScript(source, code.toString(), base); 113 | } else { 114 | _ref2 = (notSources[source] = true); 115 | } 116 | return _ref2; 117 | } 118 | compilePath; 119 | 120 | function findDirectoryIndex(source) { 121 | var ext, index, _i, _ref, _ref0; 122 | _ref = jisp.fileExtensions; 123 | for (_i = 0; _i < _ref.length; ++_i) { 124 | ext = _ref[_i]; 125 | index = path.join(source, "index" + ext); 126 | try { 127 | if (fs.statSync(index).isFile()) { 128 | return _ref0 = index; 129 | } else { 130 | _ref0 = undefined; 131 | } 132 | _ref0; 133 | } catch (err) { 134 | if (!(err.code === "ENOENT")) throw err; 135 | } 136 | } 137 | console.error("Missing index.jisp in " + source); 138 | return process.exit(1); 139 | } 140 | findDirectoryIndex; 141 | 142 | function compileScript(file, input, base) { 143 | var o, options, task, t, compiled, message, _ref, _ref0; 144 | if ((typeof base === 'undefined')) base = null; 145 | o = opts; 146 | options = compileOptions(file, base); 147 | try { 148 | t = (task = { 149 | file: file, 150 | input: input, 151 | options: options 152 | }); 153 | jisp.emit("compile", task); 154 | if (o.run) { 155 | jisp.register(); 156 | _ref = jisp.run(t.input, t.options); 157 | } else { 158 | compiled = jisp.compile(t.input); 159 | t.output = compiled; 160 | jisp.emit("success", task); 161 | _ref = o.compile ? writeJs(base, t.file, t.output, options.jsPath) : printLine(t.output.trim()); 162 | } 163 | _ref0 = _ref; 164 | } catch (err) { 165 | jisp.emit("failure", err, task); 166 | if (jisp.listeners("failure").length) undefined; 167 | message = err.stack || err.toString(); 168 | printWarn(message); 169 | _ref0 = process.exit(1); 170 | } 171 | return _ref0; 172 | } 173 | compileScript; 174 | 175 | function compileStdin() { 176 | var code, stdin; 177 | code = ""; 178 | stdin = process.openStdin(); 179 | stdin.on("data", (function(buffer) { 180 | return (buffer ? (code += buffer.toString()) : undefined); 181 | })); 182 | return stdin.on("end", (function() { 183 | return compileScript(null, code); 184 | })); 185 | } 186 | compileStdin; 187 | joinTimeout = null; 188 | compileJoin = (function() { 189 | var _ref; 190 | if (!sourceCode.some((function(code) { 191 | return (code === null); 192 | }))) { 193 | clearTimeout(joinTimeout); 194 | _ref = (joinTimeout = wait(100, (function() { 195 | return compileScript(opts.join, sourceCode.join("\n"), opts.join); 196 | }))); 197 | } else { 198 | _ref = undefined; 199 | } 200 | return _ref; 201 | }); 202 | 203 | function outputPath(source, base, extension) { 204 | var basename, srcDir, dir, _ref; 205 | if ((typeof extension === 'undefined')) extension = ".js"; 206 | basename = utils.baseFileName(source, true, useWinPathSep); 207 | srcDir = path.dirname(source); 208 | if (!opts.output) { 209 | _ref = srcDir; 210 | } else if (source === base) { 211 | _ref = opts.output; 212 | } else { 213 | _ref = path.join(opts.output, path.relative(base, srcDir)); 214 | } 215 | dir = _ref; 216 | return path.join(dir, basename + extension); 217 | } 218 | outputPath; 219 | 220 | function writeJs(base, sourcePath, js, jsPath) { 221 | var jsDir; 222 | jsDir = path.dirname(jsPath); 223 | js = js; 224 | 225 | function compile() { 226 | var _ref; 227 | if (opts.compile) { 228 | if ((js.length <= 0)) js = " "; 229 | _ref = fs.writeFile(jsPath, js, (function(err) { 230 | return (err ? printLine(err.message) : undefined); 231 | })); 232 | } else { 233 | _ref = undefined; 234 | } 235 | return _ref; 236 | } 237 | compile; 238 | return fs.exists(jsDir, (function(itExists) { 239 | return (itExists ? compile() : mkdirp(jsDir, compile)); 240 | })); 241 | } 242 | writeJs; 243 | 244 | function wait(milliseconds, func) { 245 | return setTimeout(func, milliseconds); 246 | } 247 | wait; 248 | 249 | function parseOptions() { 250 | var o; 251 | optionParser = new optparse.OptionParser(switches, banner); 252 | opts = optionParser.parse(process.argv.slice(2)); 253 | o = opts; 254 | o.compile = o.compile || !!o.output; 255 | return (o.run = !o.compile); 256 | } 257 | parseOptions; 258 | 259 | function compileOptions(filename, base) { 260 | var answer, cwd, jsPath, jsDir, _ref, _ref0; 261 | answer = { 262 | filename: filename 263 | }; 264 | if (!filename) { 265 | _ref0 = answer; 266 | } else { 267 | if (base) { 268 | cwd = process.cwd(); 269 | jsPath = outputPath(filename, base); 270 | jsDir = path.dirname(jsPath); 271 | _ref = (answer = utils.merge(answer, { 272 | jsPath: jsPath, 273 | sourceRoot: path.relative(jsDir, cwd), 274 | sourceFiles: [path.relative(cwd, filename)], 275 | generatedFile: utils.baseFileName(jsPath, false, useWinPathSep) 276 | })); 277 | } else { 278 | _ref = (answer = utils.merge(answer, { 279 | sourceRoot: "", 280 | sourceFiles: [utils.baseFileName(filename, false, useWinPathSep)], 281 | generatedFile: utils.baseFileName(filename, true, useWinPathSep) + ".js" 282 | })); 283 | } 284 | _ref0 = _ref; 285 | } 286 | return _ref0; 287 | } 288 | compileOptions; 289 | 290 | function version() { 291 | return printLine("jisp version " + jisp.version); 292 | } 293 | return version; 294 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/functions.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | function concat() { 3 | var _res, lst, _i, _i0, _ref; 4 | var lists = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 5 | _res = []; 6 | _ref = lists; 7 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 8 | lst = _ref[_i0]; 9 | _res = _res.concat(lst); 10 | } 11 | return _res; 12 | } 13 | exports.concat = concat; 14 | 15 | function list() { 16 | var _i; 17 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 18 | return [].concat(args); 19 | } 20 | exports.list = list; 21 | 22 | function range(start, end) { 23 | var a, _res, _ref; 24 | if ((typeof end === 'undefined')) { 25 | end = start; 26 | start = 0; 27 | } 28 | _res = []; 29 | while (true) { 30 | if ((start <= end)) { 31 | a = start; 32 | ++start; 33 | _ref = a; 34 | } else { 35 | _ref = undefined; 36 | break; 37 | } 38 | if (typeof _ref !== 'undefined') _res.push(_ref); 39 | } 40 | return _res; 41 | } 42 | return exports.range = range; 43 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/index.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var key, val, _ref; 3 | _ref = require("./jisp"); 4 | for (key in _ref) { 5 | val = _ref[key]; 6 | exports[key] = val; 7 | } 8 | return; 9 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/lex.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | function concat() { 3 | var _res, lst, _i, _i0, _ref; 4 | var lists = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 5 | _res = []; 6 | _ref = lists; 7 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 8 | lst = _ref[_i0]; 9 | _res = _res.concat(lst); 10 | } 11 | return _res; 12 | } 13 | var utils, pr, spr, isList, isAtom, isaString, isNum, isRegex, isIdentifier, isString, isKey, isDotName, isBracketName, isBracketString, isPropSyntax; 14 | utils = require("./utils"); 15 | pr = utils.pr; 16 | spr = utils.spr; 17 | isList = utils.isList; 18 | isAtom = utils.isAtom; 19 | isaString = utils.isaString; 20 | isNum = utils.isNum; 21 | isRegex = utils.isRegex; 22 | isIdentifier = utils.isIdentifier; 23 | isString = utils.isString; 24 | isKey = utils.isKey; 25 | isDotName = utils.isDotName; 26 | isBracketName = utils.isBracketName; 27 | isBracketString = utils.isBracketString; 28 | isPropSyntax = utils.isPropSyntax; 29 | 30 | function printConditions(conditions) { 31 | var cond, _i, _res, _ref, _ref0; 32 | _res = []; 33 | _ref = concat(conditions); 34 | for (_i = 0; _i < _ref.length; ++_i) { 35 | cond = _ref[_i]; 36 | if (((typeof cond === "function") && ((typeof cond !== 'undefined') && (typeof cond.name !== 'undefined')))) { 37 | _ref0 = cond.name; 38 | } else if (isList(cond)) { 39 | _ref0 = printConditions(cond); 40 | } else { 41 | _ref0 = pr(cond); 42 | } 43 | if (typeof _ref0 !== 'undefined') _res.push(_ref0); 44 | } 45 | return _res 46 | .join(" "); 47 | } 48 | printConditions; 49 | 50 | function maketest(condition) { 51 | var _ref; 52 | if ((typeof condition === "function")) { 53 | _ref = (function(tokens) { 54 | return condition(tokens[0]); 55 | }); 56 | } else if (isRegex(condition)) { 57 | _ref = (function(tokens) { 58 | return condition.test(tokens[0]); 59 | }); 60 | } else if (isAtom(condition)) { 61 | _ref = (function(tokens) { 62 | return (tokens[0] === condition); 63 | }); 64 | } else if (isList(condition)) { 65 | _ref = (function(tokens) { 66 | var i, cond, _res, _ref0, _ref1; 67 | _res = []; 68 | _ref0 = condition; 69 | for (i = 0; i < _ref0.length; ++i) { 70 | cond = _ref0[i]; 71 | if (!maketest(cond)(tokens.slice(i))) { 72 | return _ref1 = false; 73 | } else { 74 | _ref1 = undefined; 75 | } 76 | if (typeof _ref1 !== 'undefined') _res.push(_ref1); 77 | } 78 | return (_res ? true : undefined); 79 | }); 80 | } else { 81 | _ref = undefined; 82 | throw Error("can't test against " + pr(condition)); 83 | } 84 | return _ref; 85 | } 86 | maketest; 87 | 88 | function demand(tokens) { 89 | var conditions, modes, condition, mode, test, err, _i; 90 | var args = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 91 | conditions = []; 92 | modes = []; 93 | while (args.length > 0) { 94 | condition = args.shift(); 95 | mode = args.shift(); 96 | conditions.push(condition); 97 | modes.push(mode); 98 | test = maketest(condition); 99 | if (test(tokens)) return lex(tokens, mode); 100 | } 101 | err = ((typeof tokens[0] === 'undefined') ? Error("unexpected end of input, probably missing ) ] }") : Error("unexpected " + pr(tokens[0]) + " in possible modes: " + modes.join(" | ") + "\n\nTested against: " + printConditions(conditions) + "\n\nTokens: " + spr(tokens.slice(0, 10)) + ((tokens.length > 10) ? " ..." : " "))); 102 | throw err; 103 | } 104 | demand; 105 | 106 | function expect(tokens) { 107 | var condition, mode, test, _i, _ref; 108 | var args = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 109 | while (args.length > 0) { 110 | condition = args.shift(); 111 | mode = args.shift(); 112 | test = maketest(condition); 113 | if (test(tokens)) { 114 | return _ref = lex(tokens, mode); 115 | } else { 116 | _ref = undefined; 117 | } 118 | _ref; 119 | } 120 | return undefined; 121 | } 122 | expect; 123 | 124 | function forbid(tokens) { 125 | var condition, _i, _i0, _res, _ref, _ref0; 126 | var args = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 127 | _res = []; 128 | _ref = args; 129 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 130 | condition = _ref[_i0]; 131 | if (maketest(condition)(tokens)) { 132 | _ref0 = undefined; 133 | throw Error("unexpected " + pr(tokens[0])); 134 | } else { 135 | _ref0 = undefined; 136 | } 137 | if (typeof _ref0 !== 'undefined') _res.push(_ref0); 138 | } 139 | return _res; 140 | } 141 | forbid; 142 | 143 | function nextProp(tokens) { 144 | return expect(tokens, "[", "property", isPropSyntax, "property"); 145 | } 146 | nextProp; 147 | 148 | function grabProperties(tokens, lexed) { 149 | var prop; 150 | while (prop = nextProp(tokens)) { 151 | ((typeof lexed === 'undefined') ? (lexed = ["get", prop]) : (lexed = ["get", lexed, prop])); 152 | } 153 | return lexed; 154 | } 155 | grabProperties; 156 | 157 | function lex(tokens, mode) { 158 | var lexed, prop, key, _ref, _ref0; 159 | if ((typeof mode === 'undefined')) mode = "default"; 160 | switch (mode) { 161 | case "default": 162 | lexed = []; 163 | if ((typeof(prop = grabProperties(tokens)) !== 'undefined')) lexed.push(prop); 164 | while (tokens.length > 0) { 165 | lexed.push(demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", "...", "spread", "…", "spread", isaString, "atom", undefined, "drop")); 166 | } 167 | _ref = grabProperties(tokens, lexed); 168 | break; 169 | case "list": 170 | demand(tokens, "(", "drop"); 171 | lexed = []; 172 | if ((typeof(prop = grabProperties(tokens)) !== 'undefined')) lexed.push(prop); 173 | while (tokens[0] !== ")") { 174 | lexed.push(demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", "...", "spread", "…", "spread", isaString, "atom")); 175 | } 176 | demand(tokens, ")", "drop"); 177 | _ref = grabProperties(tokens, lexed); 178 | break; 179 | case "emptyhash": 180 | demand(tokens, "(", "drop"); 181 | demand(tokens, ":", "drop"); 182 | demand(tokens, ")", "drop"); 183 | _ref = grabProperties(tokens, {}); 184 | break; 185 | case "hash": 186 | lexed = {}; 187 | demand(tokens, "(", "drop"); 188 | while (tokens[0] !== ")") { 189 | key = demand(tokens, isKey, "key"); 190 | demand(tokens, ":", "drop"); 191 | prop = demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", isaString, "atom"); 192 | lexed[key] = prop; 193 | } 194 | demand(tokens, ")", "drop"); 195 | _ref = grabProperties(tokens, lexed); 196 | break; 197 | case "property": 198 | if (isDotName(tokens[0])) { 199 | _ref0 = demand(tokens, isDotName, "drop"); 200 | } else if (isBracketName(tokens[0]) || isBracketString(tokens[0])) { 201 | _ref0 = demand(tokens, isBracketName, "drop", isBracketString, "drop") 202 | .slice(1, -1); 203 | } else { 204 | demand(tokens, "[", "drop"); 205 | prop = demand(tokens, "(", "list", ",", "quote", isIdentifier, "atom", isNum, "atom", isString, "atom"); 206 | demand(tokens, "]", "drop"); 207 | _ref0 = prop; 208 | } 209 | _ref = _ref0; 210 | break; 211 | case "quote": 212 | demand(tokens, "`", "drop"); 213 | _ref = (lexed = ["quote", demand(tokens, ["(", ":", ")"], "emptyhash", ["(", isKey, ":"], "hash", "(", "list", "`", "quote", ",", "unquote", isaString, "atom")]); 214 | break; 215 | case "unquote": 216 | demand(tokens, ",", "drop"); 217 | _ref = ["unquote", grabProperties(tokens, demand(tokens, "(", "list", "`", "quote", "...", "spread", "…", "spread", isIdentifier, "atom"))]; 218 | break; 219 | case "spread": 220 | demand(tokens, "...", "drop", "…", "drop"); 221 | _ref = ["spread", grabProperties(tokens, demand(tokens, "(", "list", "`", "quote", isIdentifier, "atom"))]; 222 | break; 223 | case "key": 224 | key = demand(tokens, isKey, "drop"); 225 | forbid("[", isPropSyntax); 226 | _ref = key; 227 | break; 228 | case "atom": 229 | _ref = grabProperties(tokens, demand(tokens, isaString, "drop")); 230 | break; 231 | case "drop": 232 | _ref = tokens.shift(); 233 | break; 234 | default: 235 | _ref = undefined; 236 | throw Error("unspecified lex mode: " + mode); 237 | } 238 | return _ref; 239 | } 240 | lex; 241 | return module.exports = lex; 242 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/macros.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var macHash = function() { 3 | var buffer, _i, _ref; 4 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 5 | if ((args.length === 1)) { 6 | _ref = ["do", ["=", "#_res", {}, "#_ref", args[0]], 7 | ["while", [">", "#_ref.length", 0], 8 | ["=", ["get", "#_res", ["#_ref.shift"]], 9 | ["#_ref.shift"] 10 | ] 11 | ], "#_res" 12 | ]; 13 | } else { 14 | buffer = {}; 15 | while (args.length > 0) { 16 | buffer[args.shift()] = args.shift(); 17 | } 18 | _ref = buffer; 19 | } 20 | return _ref; 21 | }; 22 | var macConcatHash = function() { 23 | var arg, _i, _i0, _res, _ref, _ref0; 24 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 25 | _res = []; 26 | _ref = args; 27 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 28 | arg = _ref[_i0]; 29 | if (typeof(_ref0 = ["spread", arg]) !== 'undefined') _res.push(_ref0); 30 | } 31 | return [":", [].concat(["concat"]).concat(_res)]; 32 | }; 33 | var macPrn = function() { 34 | var _i; 35 | var x = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 36 | return [].concat(["console.log"]).concat(x); 37 | }; 38 | var macCar = function(x) { 39 | var _i; 40 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 41 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 42 | return ["get", x, 0]; 43 | }; 44 | var macCdr = function(x) { 45 | var _i; 46 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 47 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 48 | return [ 49 | ["get", x, "\"slice\""], 1 50 | ]; 51 | }; 52 | var macInit = function(x) { 53 | var _i; 54 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 55 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 56 | return [ 57 | ["get", x, "\"slice\""], 0, -1 58 | ]; 59 | }; 60 | var macLast = function(x) { 61 | var _i; 62 | var other = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 63 | if (((typeof x === 'undefined') || (other["length"] > 0))) throw Error("expecting one argument, got: " + x + ", " + other); 64 | return ["get", [ 65 | ["get", x, "\"slice\""], -1 66 | ], 0]; 67 | }; 68 | var macLet = function() { 69 | var body, names, callArgs, name, _i; 70 | var args = 2 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []); 71 | body = arguments[_i++]; 72 | if (((args.length % 2) !== 0)) throw Error, ("expecting an even number of arguments, got " + args.length); 73 | if ((typeof body === 'undefined')) body = []; 74 | names = []; 75 | callArgs = []; 76 | while (args.length > 0) { 77 | name = args.shift(); 78 | if (true) names.push(name); 79 | callArgs.push(args.shift()); 80 | } 81 | return [].concat([ 82 | [].concat(["fn"]).concat(names).concat([body]) 83 | ]).concat(callArgs); 84 | }; 85 | 86 | function list() { 87 | var _i; 88 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 89 | return [].concat(args); 90 | } 91 | var macExist = function() { 92 | var value, comp, elements, _i, _i0, _res, _ref, _ref0; 93 | var values = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 94 | _res = []; 95 | _ref = values; 96 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 97 | value = _ref[_i0]; 98 | comp = compartmentaliseExist(value); 99 | if (typeof(_ref0 = ((comp.length > 1) ? [].concat(["and"]).concat(comp) : comp[0])) !== 'undefined') _res.push(_ref0); 100 | } 101 | elements = _res; 102 | return ((elements.length > 1) ? [].concat(["or"]).concat(elements) : elements[0]); 103 | }; 104 | var macNotExist = function() { 105 | var value, comp, elements, _i, _i0, _res, _ref, _ref0; 106 | var values = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 107 | _res = []; 108 | _ref = values; 109 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 110 | value = _ref[_i0]; 111 | comp = compartmentaliseNotExist(value); 112 | if (typeof(_ref0 = ((comp.length > 1) ? [].concat(["or"]).concat(comp) : comp[0])) !== 'undefined') _res.push(_ref0); 113 | } 114 | elements = _res; 115 | return ((elements.length > 1) ? [].concat(["and"]).concat(elements) : elements[0]); 116 | }; 117 | var macIsA = function(obj) { 118 | var _i; 119 | var types = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 120 | return [].concat(["is", ["typeof", obj]]).concat(types); 121 | }; 122 | var macIsNa = function(obj) { 123 | var _i; 124 | var types = 2 <= arguments.length ? [].slice.call(arguments, 1, _i = arguments.length - 0) : (_i = 1, []); 125 | return [].concat(["isnt", ["typeof", obj]]).concat(types); 126 | }; 127 | var macAny = function() { 128 | var value, elements, _i, _i0, _res, _ref, _ref0; 129 | var values = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []); 130 | _res = []; 131 | _ref = values; 132 | for (_i0 = 0; _i0 < _ref.length; ++_i0) { 133 | value = _ref[_i0]; 134 | if (typeof(_ref0 = ["and", ["?", value], value]) !== 'undefined') _res.push(_ref0); 135 | } 136 | elements = _res; 137 | return ((elements.length > 1) ? [].concat(["or"]).concat(elements) : elements[0]); 138 | }; 139 | var utils; 140 | utils = require("./utils"); 141 | exports[":"] = macHash; 142 | exports["::"] = macConcatHash; 143 | exports.prn = macPrn; 144 | exports.car = macCar; 145 | exports.head = macCar; 146 | exports.cdr = macCdr; 147 | exports.tail = macCdr; 148 | exports.init = macInit; 149 | exports.last = macLast; 150 | exports.let = macLet; 151 | 152 | function compartmentaliseExist(form) { 153 | var i, val, split, _ref, _res, _ref0, _ref1; 154 | if ((utils.isList(form) && (form[0] === "get"))) { 155 | _ref = list.apply(list, [].concat(compartmentaliseExist(form[1])).concat([ 156 | ["isnta", form, "'undefined'"] 157 | ])); 158 | } else if ((typeof form === "string") && utils.isIdentifier(form) && !utils.isSpecialValueStr(form)) { 159 | _res = []; 160 | _ref0 = (split = utils.splitName(form)); 161 | for (i = 0; i < _ref0.length; ++i) { 162 | val = _ref0[i]; 163 | if (typeof(_ref1 = ["isnta", split.slice(0, i + 1) 164 | .join(""), "'undefined'" 165 | ]) !== 'undefined') _res.push(_ref1); 166 | } 167 | _ref = _res; 168 | } else { 169 | _ref = [ 170 | ["isnta", form, "'undefined'"] 171 | ]; 172 | } 173 | return _ref; 174 | } 175 | compartmentaliseExist; 176 | exports["?"] = macExist; 177 | 178 | function compartmentaliseNotExist(form) { 179 | var i, val, split, _ref, _res, _ref0, _ref1; 180 | if ((utils.isList(form) && (form[0] === "get"))) { 181 | _ref = list.apply(list, [].concat(compartmentaliseNotExist(form[1])).concat([ 182 | ["isa", form, "'undefined'"] 183 | ])); 184 | } else if ((typeof form === "string") && utils.isIdentifier(form) && !utils.isSpecialValueStr(form)) { 185 | _res = []; 186 | _ref0 = (split = utils.splitName(form)); 187 | for (i = 0; i < _ref0.length; ++i) { 188 | val = _ref0[i]; 189 | if (typeof(_ref1 = ["isa", split.slice(0, i + 1) 190 | .join(""), "'undefined'" 191 | ]) !== 'undefined') _res.push(_ref1); 192 | } 193 | _ref = _res; 194 | } else { 195 | _ref = [ 196 | ["isa", form, "'undefined'"] 197 | ]; 198 | } 199 | return _ref; 200 | } 201 | compartmentaliseNotExist; 202 | exports["?!"] = macNotExist; 203 | exports.isa = macIsA; 204 | exports.isnta = macIsNa; 205 | return exports.any = macAny; 206 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/operators.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var utils, pr, spr, render, isIdentifier, assertForm, operators, singops, op, ops, stateops, opFuncs, _i, _ref, _i0, _ref0, _i1, _ref1; 3 | utils = require("./utils"); 4 | pr = utils.pr; 5 | spr = utils.spr; 6 | render = utils.render; 7 | isIdentifier = utils.isIdentifier; 8 | assertForm = utils.assertForm; 9 | 10 | function makeop(op, zv, min, max, drop) { 11 | if ((typeof min === 'undefined')) min = 0; 12 | if ((typeof max === 'undefined')) max = Infinity; 13 | if ((typeof drop === 'undefined')) drop = false; 14 | return (function(args, innerType) { 15 | var i, arg, res, _ref, _ref0, _ref1; 16 | if (assertForm(args, min, max)) { 17 | if ((args.length === 0)) { 18 | _ref0 = pr(zv); 19 | } else if ((args.length === 1) && (typeof zv !== 'undefined')) { 20 | res = zv + op + spr(args); 21 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 22 | _ref0 = res; 23 | } else if ((args.length === 1) && drop) { 24 | _ref0 = spr(args); 25 | } else if (args.length === 1) { 26 | _ref0 = (op + spr(args)); 27 | } else { 28 | _ref = args; 29 | for (i = 0; i < _ref.length; ++i) { 30 | arg = _ref[i]; 31 | args[i] = pr(arg); 32 | } 33 | res = args.join(" " + op + " "); 34 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 35 | _ref0 = res; 36 | } 37 | _ref1 = _ref0; 38 | } else { 39 | _ref1 = undefined; 40 | } 41 | return _ref1; 42 | }); 43 | } 44 | makeop; 45 | 46 | function makesing(op) { 47 | return (function(args, innerType) { 48 | return (assertForm(args, 1, 1) ? (op + " " + spr(args)) : undefined); 49 | }); 50 | } 51 | makesing; 52 | 53 | function reserved(word) { 54 | throw Error("keyword " + word + " is reserved"); 55 | } 56 | reserved; 57 | 58 | function makestate(op, min, max) { 59 | if ((typeof min === 'undefined')) min = 0; 60 | if ((typeof max === 'undefined')) max = Infinity; 61 | return (function(args, innerType) { 62 | return (assertForm(args, min, max) ? (op + " " + spr(args)) : "undefined"); 63 | }); 64 | } 65 | makestate; 66 | operators = { 67 | "++": (function(args, innerType) { 68 | var _ref, _ref0; 69 | if (assertForm(args, 1, 1)) { 70 | if (!isIdentifier(args[0])) { 71 | _ref = undefined; 72 | throw Error("expecting identifier, got ", spr(args)); 73 | } else { 74 | _ref = ("++" + spr(args)); 75 | } 76 | _ref0 = _ref; 77 | } else { 78 | _ref0 = undefined; 79 | } 80 | return _ref0; 81 | }), 82 | "--": (function(args, innerType) { 83 | var _ref, _ref0; 84 | if (assertForm(args, 1, 1)) { 85 | if (!isIdentifier(args[0])) { 86 | _ref = undefined; 87 | throw Error("expecting identifier, got ", spr(args)); 88 | } else { 89 | _ref = ("--" + spr(args)); 90 | } 91 | _ref0 = _ref; 92 | } else { 93 | _ref0 = undefined; 94 | } 95 | return _ref0; 96 | }), 97 | "is": (function(args, innerType) { 98 | var subj, arg, res, _i, _res, _ref, _ref0, _ref1; 99 | if ((args.length === 0)) { 100 | _ref1 = true; 101 | } else if (args.length === 1) { 102 | _ref1 = ("!!" + spr(args)); 103 | } else { 104 | subj = args.shift(); 105 | _res = []; 106 | _ref = args; 107 | for (_i = 0; _i < _ref.length; ++_i) { 108 | arg = _ref[_i]; 109 | if (typeof(_ref0 = (pr(subj) + " === " + pr(arg))) !== 'undefined') _res.push(_ref0); 110 | } 111 | res = _res 112 | .join(" || "); 113 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 114 | _ref1 = res; 115 | } 116 | return _ref1; 117 | }), 118 | "isnt": (function(args, innerType) { 119 | var subj, arg, res, _i, _res, _ref, _ref0, _ref1; 120 | if ((args.length === 0)) { 121 | _ref1 = false; 122 | } else if (args.length === 1) { 123 | _ref1 = ("!" + spr(args)); 124 | } else { 125 | subj = args.shift(); 126 | _res = []; 127 | _ref = args; 128 | for (_i = 0; _i < _ref.length; ++_i) { 129 | arg = _ref[_i]; 130 | if (typeof(_ref0 = (pr(subj) + " !== " + pr(arg))) !== 'undefined') _res.push(_ref0); 131 | } 132 | res = _res 133 | .join(" && "); 134 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 135 | _ref1 = res; 136 | } 137 | return _ref1; 138 | }), 139 | "or": makeop("||", undefined, 1, Infinity, true), 140 | "and": makeop("&&", undefined, 1, Infinity, true), 141 | "in": (function(args, innerType) { 142 | var res, _ref; 143 | if (assertForm(args, 2, 2)) { 144 | res = "[].indexOf.call(" + pr(args[1]) + ", " + pr(args[0]) + ") >= 0"; 145 | if ((innerType && (innerType !== "parens"))) res = "(" + res + ")"; 146 | _ref = res; 147 | } else { 148 | _ref = undefined; 149 | } 150 | return _ref; 151 | }), 152 | "of": makeop("in", undefined, 2, 2), 153 | "new": (function(args, innerType) { 154 | return (assertForm(args, 1) ? ("new " + pr(args.shift()) + "(" + spr(args) + ")") : undefined); 155 | }), 156 | "function": (function() { 157 | return reserved("function"); 158 | }), 159 | "with": (function() { 160 | return reserved("with"); 161 | }) 162 | }; 163 | singops = [ 164 | ["not", "!"], 165 | ["~", "~"], 166 | ["delete", "delete"], 167 | ["typeof", "typeof"], 168 | ["!!", "!!"] 169 | ]; 170 | _ref = singops; 171 | for (_i = 0; _i < _ref.length; ++_i) { 172 | op = _ref[_i]; 173 | operators[op[0]] = makesing(op[1]); 174 | } 175 | ops = [ 176 | ["+", undefined, 1, Infinity, true], 177 | ["-", undefined, 1], 178 | ["*", 1], 179 | ["/", 1], 180 | ["%", undefined, 1], 181 | ["==", "is"], 182 | ["===", "is"], 183 | ["!=", "isnt"], 184 | ["!==", "isnt"], 185 | ["&&", "and"], 186 | ["||", "or"], 187 | ["!", "not"], 188 | [">", undefined, 2], 189 | ["<", undefined, 2], 190 | [">=", undefined, 2], 191 | ["<=", undefined, 2], 192 | ["&", undefined, 2], 193 | ["|", undefined, 2], 194 | ["^", undefined, 2], 195 | ["<<", undefined, 2], 196 | [">>", undefined, 2], 197 | [">>>", undefined, 2], 198 | ["+=", undefined, 2], 199 | ["-=", undefined, 2], 200 | ["*=", undefined, 2], 201 | ["/=", undefined, 2], 202 | ["%=", undefined, 2], 203 | ["<<=", undefined, 2], 204 | [">>=", undefined, 2], 205 | [">>>=", undefined, 2], 206 | ["&=", undefined, 2], 207 | ["^=", undefined, 2], 208 | ["|=", undefined, 2], 209 | ["instanceof", undefined, 2, 2], 210 | [",", undefined, 2, 2] 211 | ]; 212 | _ref0 = ops; 213 | for (_i0 = 0; _i0 < _ref0.length; ++_i0) { 214 | op = _ref0[_i0]; 215 | (typeof op[1] === "string") ? operators[op[0]] = operators[op[1]]: operators[op[0]] = makeop.apply(makeop, [].concat(op)); 216 | } 217 | stateops = [ 218 | ["return", 0, 1], 219 | ["break", 0, 1], 220 | ["continue", 0, 0], 221 | ["throw", 1, 1] 222 | ]; 223 | _ref1 = stateops; 224 | for (_i1 = 0; _i1 < _ref1.length; ++_i1) { 225 | op = _ref1[_i1]; 226 | operators[op[0]] = makestate(op[0]); 227 | } 228 | exports.operators = operators; 229 | opFuncs = {}; 230 | 231 | function add() { 232 | var _i2; 233 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 234 | args.unshift(0); 235 | return ((args.length === 0) ? 0 : args.reduce((function() { 236 | return (arguments[0] + arguments[1]); 237 | }))); 238 | } 239 | add; 240 | 241 | function sub() { 242 | var _i2; 243 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 244 | args.unshift(0); 245 | return ((args.length === 0) ? 0 : args.reduce((function() { 246 | return (arguments[0] - arguments[1]); 247 | }))); 248 | } 249 | sub; 250 | 251 | function mul() { 252 | var _i2; 253 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 254 | args.unshift(1); 255 | return ((args.length === 0) ? 1 : args.reduce((function() { 256 | return (arguments[0] * arguments[1]); 257 | }))); 258 | } 259 | mul; 260 | 261 | function div() { 262 | var _i2; 263 | var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i2 = arguments.length - 0) : (_i2 = 0, []); 264 | args.unshift(1); 265 | return ((args.length === 0) ? 1 : args.reduce((function() { 266 | return (arguments[0] / arguments[1]); 267 | }))); 268 | } 269 | div; 270 | return exports.opFuncs = opFuncs; 271 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/optparse.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var repeat, OptionParser, long_flag, short_flag, multi_flag, optional; 3 | repeat = require("./utils").repeat; 4 | exports.OptionParser = (OptionParser = (function() { 5 | function OptionParser(rules, banner) { 6 | this.banner = banner; 7 | this.rules = buildRules(rules); 8 | return this; 9 | } 10 | OptionParser; 11 | OptionParser.prototype.parse = (function(args) { 12 | var options, skippingArgument, originalArgs, i, arg, pos, isOption, seenNonOptionArg, matchedRule, rule, value, _ref, _i, _ref0; 13 | options = { 14 | arguments: [] 15 | }; 16 | skippingArgument = false; 17 | originalArgs = args; 18 | args = normaliseArguments(args); 19 | _ref = args; 20 | for (i = 0; i < _ref.length; ++i) { 21 | arg = _ref[i]; 22 | if (skippingArgument) { 23 | skippingArgument = false; 24 | continue; 25 | } 26 | if ((arg === "--")) { 27 | pos = originalArgs.indexOf("--"); 28 | options.arguments = options.arguments.concat(originalArgs.slice(pos + 1)); 29 | break; 30 | } 31 | isOption = !!(arg.match(long_flag) || arg.match(short_flag)); 32 | seenNonOptionArg = options.arguments.length > 0; 33 | if (!seenNonOptionArg) { 34 | matchedRule = false; 35 | _ref0 = this.rules; 36 | for (_i = 0; _i < _ref0.length; ++_i) { 37 | rule = _ref0[_i]; 38 | if ((arg === rule.shortFlag || arg === rule.longFlag)) { 39 | value = true; 40 | if (rule.hasArgument) { 41 | skippingArgument = true; 42 | value = args[i + 1]; 43 | } 44 | options[rule.name] = (rule.isList ? options[rule.name] || [].concat(value) : value); 45 | matchedRule = true; 46 | break; 47 | } 48 | } 49 | if ((isOption && !matchedRule)) throw new Error(("unrecognised option: " + arg)); 50 | } 51 | if ((seenNonOptionArg || !isOption)) options.arguments.push(arg); 52 | } 53 | return options; 54 | }); 55 | OptionParser.prototype.help = (function() { 56 | var lines, rule, spaces, letPart, _i, _ref; 57 | lines = []; 58 | if (this.banner) lines.unshift(this.banner + "\n"); 59 | _ref = this.rules; 60 | for (_i = 0; _i < _ref.length; ++_i) { 61 | rule = _ref[_i]; 62 | spaces = 15 - rule.longFlag.length; 63 | spaces = ((spaces > 0) ? repeat(" ", spaces) : ""); 64 | letPart = (rule.shortFlag ? (rule.shortFlag + ", ") : " "); 65 | lines.push(" " + letPart + rule.longFlag + spaces + rule.description); 66 | } 67 | return ("\n" + lines.join("\n") + "\n"); 68 | }); 69 | return OptionParser; 70 | })()); 71 | long_flag = /^(--\w[\w\-]*)/; 72 | short_flag = /^(-\w)$/; 73 | multi_flag = /^-(\w{2,})/; 74 | optional = /\[(\w+(\*?))\]/; 75 | 76 | function buildRules(rules) { 77 | var tuple, _i, _res, _ref, _ref0; 78 | _res = []; 79 | _ref = rules; 80 | for (_i = 0; _i < _ref.length; ++_i) { 81 | tuple = _ref[_i]; 82 | if ((tuple.length < 3)) tuple.unshift(null); 83 | if (typeof(_ref0 = buildRule.apply(buildRule, [].concat(tuple))) !== 'undefined') _res.push(_ref0); 84 | } 85 | return _res; 86 | } 87 | buildRules; 88 | 89 | function buildRule(shortFlag, longFlag, description, options) { 90 | var match; 91 | if ((typeof options === 'undefined')) options = {}; 92 | match = longFlag.match(optional); 93 | longFlag = longFlag.match(long_flag)[1]; 94 | return { 95 | name: longFlag.substr(2), 96 | shortFlag: shortFlag, 97 | longFlag: longFlag, 98 | description: description, 99 | hasArgument: !!(match && match[1]), 100 | isList: !!(match && match[2]) 101 | } 102 | } 103 | buildRule; 104 | 105 | function normaliseArguments(args) { 106 | var result, arg, match, l, _i, _ref, _i0, _ref0; 107 | args = args.slice(0); 108 | result = []; 109 | _ref = args; 110 | for (_i = 0; _i < _ref.length; ++_i) { 111 | arg = _ref[_i]; 112 | if ((match = arg.match(multi_flag))) { 113 | _ref0 = match[1].split(""); 114 | for (_i0 = 0; _i0 < _ref0.length; ++_i0) { 115 | l = _ref0[_i0]; 116 | result.push("-" + l); 117 | } 118 | } else { 119 | result.push(arg); 120 | } 121 | } 122 | return result; 123 | } 124 | return normaliseArguments; 125 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/parse.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var utils; 3 | utils = require("./utils"); 4 | 5 | function parse(form) { 6 | var i, val, key, _ref, _ref0, _ref1; 7 | if (utils.isList(form)) { 8 | _ref = form; 9 | for (i = 0; i < _ref.length; ++i) { 10 | val = _ref[i]; 11 | form[i] = parse(val); 12 | } 13 | _ref0 = form; 14 | } else if (utils.isHash(form)) { 15 | _ref1 = form; 16 | for (key in _ref1) { 17 | val = _ref1[key]; 18 | form[key] = parse(val); 19 | } 20 | _ref0 = form; 21 | } else { 22 | form = utils.typify(form); 23 | _ref0 = (/^#(\d+)/.test(form) ? form.replace(/^#(\d+)/, "arguments[$1]") : form); 24 | } 25 | return _ref0; 26 | } 27 | return module.exports = parse; 28 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/register.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var child_process, path, utils, jisp, ext, _i, _ref; 3 | child_process = require("child_process"); 4 | path = require("path"); 5 | utils = require("./utils"); 6 | jisp = require("./jisp"); 7 | 8 | function loadFile(module, filename) { 9 | return module._compile(jisp.compileFile(filename), filename); 10 | } 11 | loadFile; 12 | if (require.extensions) { 13 | _ref = jisp.fileExtensions; 14 | for (_i = 0; _i < _ref.length; ++_i) { 15 | ext = _ref[_i]; 16 | require.extensions[ext] = loadFile; 17 | } 18 | } 19 | return; 20 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/repl.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var vm, nodeREPL, jisp, replDefaults, start; 3 | vm = require("vm"); 4 | nodeREPL = require("repl"); 5 | jisp = require("./jisp"); 6 | replDefaults = { 7 | useGlobal: true, 8 | prompt: "jisp> ", 9 | eval: (function(input, context, filename, cb) { 10 | var js, result, _ref; 11 | input = input.replace(/\uFF00/g, "\n"); 12 | input = input.replace(/^\(([^]*)\n\)$/g, "$1"); 13 | try { 14 | js = jisp.compile(input, { 15 | wrap: false, 16 | repl: true 17 | }); 18 | console.log("-- compiled:"); 19 | console.log(js); 20 | console.log("-- executing:"); 21 | result = vm.runInThisContext(js, filename); 22 | _ref = cb(null, result); 23 | } catch (err) { 24 | _ref = cb(err); 25 | } 26 | return _ref; 27 | }) 28 | }; 29 | 30 | function enableMultiline(repl) { 31 | var rli, inputStream, outputStream, origPrompt, multiline, lineListener; 32 | rli = repl.rli; 33 | inputStream = repl.inputStream; 34 | outputStream = repl.outputStream; 35 | origPrompt = (((typeof repl !== 'undefined') && (typeof repl._prompt !== 'undefined')) ? repl._prompt : repl.prompt); 36 | multiline = { 37 | enabled: false, 38 | prompt: origPrompt.replace(/^[^>\s]*>?/, (function(x) { 39 | return x.replace(/./g, "."); 40 | })), 41 | buffer: "" 42 | }; 43 | lineListener = rli.listeners("line")[0]; 44 | rli.removeListener("line", lineListener); 45 | return rli.on("line", (function(cmd) { 46 | var m, opened, closed, _ref, _ref0, _ref1; 47 | if (multiline.enabled) { 48 | multiline.buffer += (cmd + "\n"); 49 | opened = ((typeof(m = multiline.buffer.match(/\(/g)) !== 'undefined') ? m.length : 0); 50 | closed = ((typeof(m = multiline.buffer.match(/\)/g)) !== 'undefined') ? m.length : 0); 51 | if ((opened > closed)) { 52 | rli.setPrompt(multiline.prompt); 53 | _ref = rli.prompt(true); 54 | } else { 55 | multiline.enabled = false; 56 | multiline.buffer = multiline.buffer.replace(/\n/g, "\uFF00"); 57 | rli.emit("line", multiline.buffer); 58 | multiline.buffer = ""; 59 | rli.setPrompt(origPrompt); 60 | _ref = rli.prompt(true); 61 | } 62 | _ref1 = _ref; 63 | } else { 64 | opened = ((typeof(m = cmd.match(/\(/g)) === "string") ? m.length : 0); 65 | closed = ((typeof(m = cmd.match(/\)/g)) === "string") ? m.length : 0); 66 | if ((opened > closed)) { 67 | multiline.enabled = true; 68 | multiline.buffer += (cmd + "\n"); 69 | rli.setPrompt(multiline.prompt); 70 | _ref0 = rli.prompt(true); 71 | } else { 72 | _ref0 = lineListener(cmd); 73 | } 74 | _ref1 = _ref0; 75 | } 76 | return _ref1; 77 | })); 78 | } 79 | enableMultiline; 80 | return exports.start = (start = (function() { 81 | var repl; 82 | repl = nodeREPL.start(replDefaults); 83 | repl.on("exit", (function() { 84 | return repl.outputStream.write("\n"); 85 | })); 86 | enableMultiline(repl); 87 | return repl; 88 | })); 89 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/tokenise.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var tokens, recode, recomment, redstring, resstring, rereg; 3 | tokens = []; 4 | recode = /^[^]*?(?=;.*[\n\r]?|""|"[^]*?(?:[^\\]")|''|'[^]*?(?:[^\\]')|\/[^\s]+\/[\w]*)/; 5 | recomment = /^;.*[\n\r]?/; 6 | redstring = /^""|^"[^]*?(?:[^\\]")[^\s):\[\]\{\}]*/; 7 | resstring = /^''|^'[^]*?(?:[^\\]')[^\s):\[\]\{\}]*/; 8 | rereg = /^\/[^\s]+\/[\w]*[^\s)]*/; 9 | 10 | function grate(str) { 11 | return str 12 | .replace(/;.*$/gm, "") 13 | .replace(/\{/g, "(fn (") 14 | .replace(/\}/g, "))") 15 | .replace(/\(/g, " ( ") 16 | .replace(/\)/g, " ) ") 17 | .replace(/\[$/g, " [ ") 18 | .replace(/\['/g, " [ '") 19 | .replace(/\["/g, ' [ "') 20 | .replace(/'\]/g, "' ] ") 21 | .replace(/"\]/g, '" ] ') 22 | .replace(/\[[\s]*\(/g, " [ ( ") 23 | .replace(/\)[\s]*\]/g, " ) ] ") 24 | .replace(/([^:]):(?!\:)/g, "$1 : ") 25 | .replace(/`/g, " ` ") 26 | .replace(/,/g, " , ") 27 | .replace(/\.\.\./g, " ... ") 28 | .replace(/…/g, " … ") 29 | .trim() 30 | .split(/\s+/); 31 | } 32 | grate; 33 | 34 | function concatNewLines(str) { 35 | return str.replace(/\n|\n\r/g, "\\n"); 36 | } 37 | concatNewLines; 38 | 39 | function match(str, re) { 40 | var mask; 41 | return (((mask = str.match(re)) && (mask[0].length > 0)) ? mask[0] : null); 42 | } 43 | match; 44 | 45 | function tokenise(str) { 46 | var mask; 47 | tokens = []; 48 | while ((str = str.trim()).length > 0) { 49 | if ((mask = match(str, recode))) { 50 | tokens.push.apply(tokens, [].concat(grate(mask))); 51 | str = str.replace(recode, ""); 52 | } else if (mask = match(str, recomment)) { 53 | str = str.replace(recomment, ""); 54 | } else if (mask = match(str, redstring)) { 55 | tokens.push(concatNewLines(mask)); 56 | str = str.replace(redstring, ""); 57 | } else if (mask = match(str, resstring)) { 58 | tokens.push(concatNewLines(mask)); 59 | str = str.replace(resstring, ""); 60 | } else if (mask = match(str, rereg)) { 61 | tokens.push(mask); 62 | str = str.replace(rereg, ""); 63 | } else { 64 | tokens.push.apply(tokens, [].concat(grate(str))); 65 | str = ""; 66 | } 67 | } 68 | return tokens.filter((function(x) { 69 | return ((typeof x !== 'undefined') && (x !== "" && x !== undefined && x !== null)); 70 | })); 71 | } 72 | tokenise; 73 | return module.exports = tokenise; 74 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/uniq.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var utils; 3 | utils = require("./utils"); 4 | 5 | function Uniq(uniq, store) { 6 | var of, name, _ref; 7 | this.parent = uniq; 8 | this.store = {}; 9 | if (store) { 10 | _ref = store; 11 | for (of in _ref) { 12 | name = _ref[of]; 13 | this.store[of] = name; 14 | } 15 | } 16 | return this; 17 | } 18 | Uniq; 19 | Uniq.prototype.find = (function(func) { 20 | var uniq, ref, _ref; 21 | uniq = this; 22 | while (typeof uniq !== 'undefined') { 23 | if ((ref = func.call(uniq))) { 24 | _ref = undefined; 25 | break; 26 | } else { 27 | _ref = (uniq = uniq.parent); 28 | } 29 | _ref; 30 | } 31 | return ref; 32 | }); 33 | Uniq.prototype.findOut = (function(func) { 34 | return (((typeof this !== 'undefined') && (typeof this.parent !== 'undefined')) ? this.parent.find(func) : undefined); 35 | }); 36 | Uniq.prototype.has = (function(key) { 37 | return ([].indexOf.call(Object.keys(this.store), key) >= 0); 38 | }); 39 | Uniq.prototype.conflict = (function(key) { 40 | return this.findOut((function() { 41 | return this.has(key); 42 | })); 43 | }); 44 | Uniq.prototype.resolve = (function(key) { 45 | var oldkey; 46 | oldkey = key; 47 | while (this.conflict(key)) { 48 | key = utils.plusname(key); 49 | } 50 | return (this.store[key] = (this.store[oldkey] = (function(name) { 51 | return name.replace(RegExp("^" + oldkey), key); 52 | }))); 53 | }); 54 | Uniq.prototype.checkAndReplace = (function(name) { 55 | var key; 56 | key = utils.getServicePart(name); 57 | if (!this.has(key)) this.resolve(key); 58 | return this.store[key](name); 59 | }); 60 | return module.exports = Uniq; 61 | })['call'](this); -------------------------------------------------------------------------------- /lib/jisp/utils.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var keywords, specialValues; 3 | exports.keywords = (keywords = ["return", "break", "continue", "throw", "delete"]); 4 | 5 | function kwtest(str) { 6 | var kw, re, _i, _res, _ref, _ref0; 7 | _res = []; 8 | _ref = keywords; 9 | for (_i = 0; _i < _ref.length; ++_i) { 10 | kw = _ref[_i]; 11 | if (typeof(_ref0 = ("^" + kw + " |^" + kw + "$")) !== 'undefined') _res.push(_ref0); 12 | } 13 | re = RegExp(_res 14 | .join("|")); 15 | return re.test(str); 16 | } 17 | exports.kwtest = kwtest; 18 | exports.specialValues = (specialValues = ["undefined", "null", "true", "false", "yes", "no", "Infinity", "NaN", "this"]); 19 | 20 | function isSpecialValueStr(str) { 21 | return ([].indexOf.call(specialValues, str) >= 0); 22 | } 23 | exports.isSpecialValueStr = isSpecialValueStr; 24 | 25 | function isSpecialValue(form) { 26 | return ((typeof form === "undefined") || (form === null) || ((typeof form === "number") && isNaN(form)) || (form === Infinity) || (typeof form === "boolean")); 27 | } 28 | exports.isSpecialValue = isSpecialValue; 29 | 30 | function isAtom(form) { 31 | return ((form === undefined || form === null) || /^\/[^\s\/]+\/[\w]*$/.test(form) || (typeof form === "number" || typeof form === "string" || typeof form === "boolean")); 32 | } 33 | exports.isAtom = isAtom; 34 | 35 | function isaString(form) { 36 | return (typeof form === "string"); 37 | } 38 | exports.isaString = isaString; 39 | 40 | function isList(form) { 41 | return Array.isArray(form); 42 | } 43 | exports.isList = isList; 44 | 45 | function isHash(form) { 46 | return (!isAtom(form) && !isList(form) && !(typeof form === "function")); 47 | } 48 | exports.isHash = isHash; 49 | 50 | function isBlankObject(form) { 51 | var _ref, _err; 52 | try { 53 | _ref = Object.keys(form).length === 0; 54 | } catch (_err) { 55 | _ref = false; 56 | } 57 | return _ref; 58 | } 59 | exports.isBlankObject = isBlankObject; 60 | 61 | function isKey(form) { 62 | return (isAtom(form) && (isString(form) || isIdentifier(form) || isNum(form))); 63 | } 64 | exports.isKey = isKey; 65 | 66 | function isServiceName(form) { 67 | return ((typeof form === "string") && /^#/.test(form) && !/^#$|^#\d|^#\.|^#\[/.test(form)); 68 | } 69 | exports.isService = isServiceName; 70 | 71 | function getServicePart(form) { 72 | return form.match(/^#[^.[]+/)[0]; 73 | } 74 | exports.getServicePart = getServicePart; 75 | 76 | function isVarName(form) { 77 | return (isAtom(form) && /^[$#_A-Za-z]{1}$|^[$#_A-Za-z]+[$_\w]*(?:[$_\w](?!\.))+$/.test(form)); 78 | } 79 | exports.isVarName = isVarName; 80 | 81 | function isIdentifier(form) { 82 | return (isAtom(form) && /^[$#_A-Za-z]{1}[$_\w()]*((\.[$#_A-Za-z]{1}[$_\w()]*)|(\[[$_.\w()\[\]]+\])|(\['.*'\])|(\[".*"\]))*$/.test(form)); 83 | } 84 | exports.isIdentifier = isIdentifier; 85 | 86 | function isString(form) { 87 | return (isAtom(form) && /^".*"$|^'.*'$/.test(form)); 88 | } 89 | exports.isString = isString; 90 | 91 | function isRegex(form) { 92 | return (isAtom(form) && /^\/[^\s]+\/[\w]*[^\s)]*/.test(form)); 93 | } 94 | exports.isRegex = isRegex; 95 | 96 | function isNum(form) { 97 | return (isAtom(form) && (typeof typify(form) === "number")); 98 | } 99 | exports.isNum = isNum; 100 | 101 | function isPrimitive(form) { 102 | return (isRegex(form) || isNum(form) || (form === undefined || form === null || form === true || form === false)); 103 | } 104 | exports.isPrimitive = isPrimitive; 105 | 106 | function isArgHash(form) { 107 | return (isAtom(form) && /^#[\d]+$/.test(form)); 108 | } 109 | exports.isArgHash = isArgHash; 110 | 111 | function isArgsHash(form) { 112 | return (isAtom(form) && /^#$/.test(form)); 113 | } 114 | exports.isArgsHash = isArgsHash; 115 | 116 | function isArgHashNotation(form) { 117 | return (isArgHash(form) || isArgsHash(form)); 118 | } 119 | exports.isArgHashNotation = isArgHashNotation; 120 | 121 | function isDotName(form) { 122 | return (isAtom(form) && /^\.[$#_A-Za-z]{1}$|^\.[$#_A-Za-z]+[$_.\w]*(?:[$_\w](?!\.))+$/.test(form)); 123 | } 124 | exports.isDotName = isDotName; 125 | 126 | function isBracketName(form) { 127 | return (isAtom(form) && (/^\[[$#_A-Za-z]{1}\]$|^\[[$#_A-Za-z]+[$_.\w()]*(?:[$_\w()](?!\.))+\]$/.test(form) || /^\[[\d]+\]/.test(form))); 128 | } 129 | exports.isBracketName = isBracketName; 130 | 131 | function isBracketString(form) { 132 | return (isAtom(form) && /^\[".*"\]$|^\['.*'\]$/.test(form)); 133 | } 134 | exports.isBracketString = isBracketString; 135 | 136 | function isPropSyntax(form) { 137 | return (isAtom(form) && (isDotName(form) || isBracketName(form) || isBracketString(form))); 138 | } 139 | exports.isPropSyntax = isPropSyntax; 140 | 141 | function typify(form) { 142 | var _ref; 143 | if (!isAtom(form)) { 144 | _ref = undefined; 145 | throw Error("expecting atom, got " + pr(form)); 146 | } else if (isBlankObject(form)) { 147 | _ref = form; 148 | } else if (typeof form === "undefined") { 149 | _ref = undefined; 150 | } else if (form === "null") { 151 | _ref = null; 152 | } else if (form === "true" || form === "yes") { 153 | _ref = true; 154 | } else if (form === "false" || form === "no") { 155 | _ref = false; 156 | } else if (!isNaN(Number(form))) { 157 | _ref = Number(form); 158 | } else if (isRegex(form)) { 159 | _ref = form; 160 | } else if (typeof form === "string") { 161 | _ref = form; 162 | } else { 163 | _ref = undefined; 164 | throw Error("syntax error: unrecognised type of " + pr(form)); 165 | } 166 | return _ref; 167 | } 168 | exports.typify = typify; 169 | 170 | function assertForm(form, min, max, first) { 171 | var _ref; 172 | if ((typeof min === 'undefined')) min = 0; 173 | if ((typeof max === 'undefined')) max = Infinity; 174 | if (!isList(form)) { 175 | _ref = undefined; 176 | throw Error("expecting list, got " + form); 177 | } else if (!((form.length >= min) && (form.length <= max))) { 178 | _ref = undefined; 179 | throw Error("expecting between " + min + " and " + max + " arguments, got " + form.length + ": " + pr(form)); 180 | } else if ((typeof first !== 'undefined') && (form[0] !== first)) { 181 | _ref = undefined; 182 | throw Error("expecting " + pr(first) + " as first element, got " + pr(form[0])); 183 | } else { 184 | _ref = form; 185 | } 186 | return _ref; 187 | } 188 | exports.assertForm = assertForm; 189 | 190 | function assertExp(exp, test, expect) { 191 | var _ref; 192 | if ((typeof expect === 'undefined')) expect = "valid expression"; 193 | if (test(exp)) { 194 | _ref = true; 195 | } else { 196 | _ref = undefined; 197 | throw Error("expecting " + pr(expect) + ", got " + pr(exp)); 198 | } 199 | return _ref; 200 | } 201 | exports.assertExp = assertExp; 202 | 203 | function splitName(name) { 204 | var re, reDot, reBracket, reBracketGreedy, res, reg; 205 | re = /\.[$_\w]+$|\[[^\[\]]+\]$|\[.+\]$/; 206 | reDot = /\.[$_\w]+$/; 207 | reBracket = /\[[^\[\]]+\]$/; 208 | reBracketGreedy = /\[.+\]$/; 209 | res = []; 210 | while (name.match(re)) { 211 | reg = (name.match(reDot) && reDot) || (name.match(reBracket) && reBracket) || (name.match(reBracketGreedy) && reBracketGreedy); 212 | res.unshift(name.match(reg)[0]); 213 | name = name.replace(reg, ""); 214 | } 215 | res.unshift(name); 216 | return res; 217 | } 218 | exports.splitName = splitName; 219 | 220 | function plusname(name) { 221 | return (isNaN(Number(name["slice"](-1)[0])) ? (name + 0) : (name["slice"](0, -1) + (1 + Number(name["slice"](-1)[0])))); 222 | } 223 | exports.plusname = plusname; 224 | 225 | function pr(item) { 226 | var res, key, val, _ref, _ref0, _i, _ref1; 227 | if (isAtom(item)) { 228 | _ref = ("" + item) 229 | .replace(/;$/, ""); 230 | } else if (isHash(item)) { 231 | res = ""; 232 | _ref0 = item; 233 | for (key in _ref0) { 234 | val = _ref0[key]; 235 | res += (key + ": " + pr(val) + ", "); 236 | } 237 | _ref = ("{ " + res.slice(0, -2) + " }"); 238 | } else if (isList(item)) { 239 | res = ""; 240 | _ref1 = item; 241 | for (_i = 0; _i < _ref1.length; ++_i) { 242 | val = _ref1[_i]; 243 | res += (pr(val) + ", "); 244 | } 245 | _ref = ("[ " + res.slice(0, -2) + " ]"); 246 | } else { 247 | _ref = ("" + item); 248 | } 249 | return _ref; 250 | } 251 | exports.pr = pr; 252 | 253 | function spr(item) { 254 | var res, val, _i, _ref, _ref0; 255 | if (isList(item)) { 256 | res = ""; 257 | _ref = item; 258 | for (_i = 0; _i < _ref.length; ++_i) { 259 | val = _ref[_i]; 260 | res += (pr(val) + ", "); 261 | } 262 | _ref0 = res.slice(0, res.length - 2); 263 | } else { 264 | _ref0 = undefined; 265 | throw Error("can only print-spread lists"); 266 | } 267 | return _ref0; 268 | } 269 | exports.spr = spr; 270 | 271 | function render(buffer) { 272 | var i, exp, res, _ref; 273 | _ref = buffer; 274 | for (i = 0; i < _ref.length; ++i) { 275 | exp = _ref[i]; 276 | if (((isList(exp) && (exp.length === 0)) || (typeof exp === "undefined") || (exp === ""))) { 277 | buffer[i] = undefined; 278 | } else { 279 | res = ((typeof exp === "string") ? exp.trim() : pr(exp)); 280 | if ((isHash(exp) || /^function\s*\(/.test(res))) res = "(" + res + ")"; 281 | if (!/:$|\}$|;$/.test(res.slice(-1))) res += ";"; 282 | buffer[i] = res; 283 | } 284 | } 285 | return buffer.join(" ") 286 | .trim(); 287 | } 288 | exports.render = render; 289 | 290 | function deParenthesise(str) { 291 | var _ref; 292 | if ((typeof str === "string")) { 293 | while (str.match(/^\({1}/) && str.match(/\){1}$/)) { 294 | (str = str 295 | .replace(/^\({1}/, "") 296 | .replace(/\){1}$/, "")); 297 | } 298 | _ref = str; 299 | } else { 300 | _ref = str; 301 | } 302 | return _ref; 303 | } 304 | exports.deParenthesise = deParenthesise; 305 | 306 | function dePairParenthesise(str) { 307 | var _ref; 308 | if ((typeof str === "string")) { 309 | while (str.match(/^\({2}/) && str.match(/\){2}$/)) { 310 | (str = str 311 | .replace(/^\({2}/, "(") 312 | .replace(/\){2}$/, ")")); 313 | } 314 | _ref = str; 315 | } else { 316 | _ref = str; 317 | } 318 | return _ref; 319 | } 320 | exports.dePairParenthesise = dePairParenthesise; 321 | 322 | function merge(options, overrides) { 323 | return extend(extend({}, options), overrides); 324 | } 325 | exports.merge = merge; 326 | 327 | function extend(object, properties) { 328 | var key, val, _ref; 329 | _ref = properties; 330 | for (key in _ref) { 331 | val = _ref[key]; 332 | object[key] = val; 333 | } 334 | return object; 335 | } 336 | exports.extend = extend; 337 | 338 | function baseFileName(file, stripExt, useWinPathSep) { 339 | var pathSep, parts; 340 | if ((typeof stripExt === 'undefined')) stripExt = false; 341 | if ((typeof useWinPathSep === 'undefined')) useWinPathSep = false; 342 | pathSep = (useWinPathSep ? /\\|\// : /\//); 343 | parts = file.split(pathSep); 344 | file = parts["slice"](-1)[0]; 345 | if (!(stripExt && (file.indexOf(".") >= 0))) return file; 346 | parts = file.split("."); 347 | parts.pop(); 348 | if (((parts["slice"](-1)[0] === "jisp") && (parts.length > 1))) parts.pop(); 349 | return parts.join("."); 350 | } 351 | exports.baseFileName = baseFileName; 352 | 353 | function repeat(str, n) { 354 | var res; 355 | res = ""; 356 | while (n > 0) { 357 | if ((n & 1)) res += str; 358 | n >>>= 1; 359 | str += str; 360 | } 361 | return res; 362 | } 363 | exports.repeat = repeat; 364 | 365 | function isJisp(file) { 366 | return /\.jisp$/.test(file); 367 | } 368 | return exports.isJisp = isJisp; 369 | })['call'](this); -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | (MIT License) 2 | 3 | Copyright (c) 2014 Mitranim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jisp", 3 | "version": "0.3.3", 4 | "description": "The modern JavaScript: a programmable language", 5 | "keywords": [ 6 | "javascript", 7 | "language", 8 | "lisp", 9 | "compiler" 10 | ], 11 | "engines": { 12 | "node": ">=0.8.0" 13 | }, 14 | "directories": { 15 | "lib": "./lib/jisp" 16 | }, 17 | "main": "./lib/jisp/jisp", 18 | "bin": { 19 | "jisp": "./bin/jisp" 20 | }, 21 | "scripts": { 22 | "test": "./bin/build && ./bin/build", 23 | "reset": "./bin/build -r", 24 | "build": "./bin/build -s", 25 | "prepublish": "./bin/build -s" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/Mitranim/jisp.git" 30 | }, 31 | "homepage": "http://jisp.io", 32 | "author": "Mitranim", 33 | "license": "MIT", 34 | "dependencies": { 35 | "mkdirp": "latest", 36 | "js-beautify": "latest" 37 | }, 38 | "devDependencies": { 39 | "yargs": "latest" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | > Note: I apologise for the lack of updates. I've been preparing [0.4.0](https://github.com/Mitranim/jisp/tree/0.4.0), which is a complete rewrite of the compiler with a bunch of breaking changes. It revises some parts of the language, dropping dead end ideas and focusing on the core features. Unfortunately I'm busy with some other projects right now. 2 | 3 | ## Description 4 | 5 | Jisp is [the modern JavaScript for the modern developer](http://jisp.io). Its macro system lets you treat code as data and write functions that write code for you. Reuse code without runtime limitations, make your code more abstract and shorter, reprogram the language itself. 6 | 7 | Jisp's extremely simple syntax protects against common JS pitfalls, and it builds some common coding patterns right into the language, helping keep your code short. 8 | 9 | See the [interactive online documentation](http://jisp.io). You can contribute to the documentation by sending pull requests to the [gh-pages](https://github.com/Mitranim/jisp/tree/gh-pages) branch of this repo. 10 | 11 | ## Installation and Usage 12 | 13 | Get [Node.js](http://nodejs.org). This will give you the local `node` runtime and the `npm` package manager. Install jisp with `npm`: 14 | 15 | $ npm install -g jisp 16 | 17 | Alternatively, download the source, run `npm install` to get the dependencies, and use `./bin/jisp` and `./jisp/jisp.js` as entry points. 18 | 19 | Require in Node, registering the file extension: 20 | 21 | require('jisp/register'); 22 | 23 | This allows you to `require` jisp scripts directly from your code, like so: 24 | 25 | require('./app.jisp'); 26 | 27 | Launch an interactive REPL: 28 | 29 | $ jisp 30 | jisp> 31 | 32 | Compile a file or directory: 33 | 34 | $ jisp -c 35 | 36 | Stream-compile with [gulp-jisp](https://github.com/Mitranim/gulp-jisp). 37 | 38 | While not recommended for production, jisp can be directly used in the browser. Include the `browser/jisp.js` file with your webpage. It registers the `text/jisp` script type to automatically compile and run jisp scripts loaded with `src` or included in script tags. It also exposes a global object with the `compile` and `eval` methods for jisp code. This is how the [documentation](http://jisp.io) is implemented. 39 | 40 | When hacking at the compiler, use the following commands in the project dir: 41 | 42 | npm test -- recompiles dev from src twice, using the dev compiler 43 | npm run reset -- disaster recovery: recompiles dev with lib (stable) 44 | npm run build -- recompiles lib with dev (prepublish) 45 | 46 | Super basic Sublime Text build system (OS X): 47 | * `sudo npm install -g jisp` 48 | * `Tools > Build System > New Build System` 49 | * put lines: 50 | 51 | { 52 | "cmd": ["jisp", "$file"], 53 | "path": "/usr/local/bin/" 54 | } 55 | 56 | * save to: `~/Library/Application Support/Sublime Text 3/Packages/User` 57 | -------------------------------------------------------------------------------- /register.js: -------------------------------------------------------------------------------- 1 | require('./lib/jisp/register'); 2 | -------------------------------------------------------------------------------- /src/browser.jisp: -------------------------------------------------------------------------------- 1 | ; Browser compatibility module 2 | ; Copied from CoffeeScript source 3 | ; ToDo add polyfill 4 | ; ToDo add source map support 5 | 6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7 | 8 | (= jisp (require "./jisp") 9 | jisp.require require 10 | compile jisp.compile) 11 | 12 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Rest ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 13 | 14 | ; Use standard JS `eval` to eval code 15 | (= jisp.eval (fn code (options (:)) (do 16 | (= options.wrap no) 17 | (eval (compile code options))))) 18 | 19 | (= jisp.run (fn code (options (:)) (do 20 | (= options.wrap no) 21 | (= compiled (compile code options)) 22 | ((Function (compile code options)))))) 23 | 24 | ; If we're not in a browser environment, end the script 25 | (if (?! window) return) 26 | 27 | ; Load remote script by XHR 28 | (= jisp.load (fn url callback (options (:)) (hold no) (do 29 | (= options.sourceFiles `(url) 30 | xhr (if window.ActiveXObject 31 | (new window.ActiveXObject "Microsoft.XMLHTTP") 32 | (new window.XMLHttpRequest))) 33 | (xhr.open "GET" url yes) 34 | (if (of `overrideMimeType xhr) (xhr.overrideMimeType "text/plain")) 35 | (= xhr.onreadystatechange (fn (do 36 | (if (is xhr.readyState 4) 37 | (if (is xhr.status 0 200) 38 | (do (= param `(xhr.responseText options)) 39 | (if (not hold) (jisp.run ...param))) 40 | (throw (new Error (+ "Could not load " url))))) 41 | (if callback (callback param))))) 42 | (xhr.send null)))) 43 | 44 | ; Compile and eval all `text/jisp` script tags 45 | ; Happens on page load 46 | (def runScripts (do 47 | (= scripts (window.document.getElementsByTagName "script") 48 | jisps `() 49 | index 0) 50 | (for s scripts 51 | (if (is s.type "text/jisp") (jisps.push s))) 52 | (def execute (do 53 | (= param jisps[index]) 54 | (if (instanceof param Array) 55 | (do (jisp.run ...param) 56 | (++ index) 57 | (execute))))) 58 | (for script i jisps (let script script i i (do 59 | (= options (:)) 60 | (if script.src 61 | (jisp.load script.src (fn param 62 | (do (= jisps[i] param) 63 | (execute))) 64 | options 65 | true) 66 | (do (= options.sourceFiles `("embedded")) 67 | (= jisps[i] `(script.innerHTML options))))))) 68 | (execute))) 69 | 70 | ; Listen for window load: decent browsers / IE 71 | (if window.addEventListener 72 | (window.addEventListener "DOMContentLoaded" runScripts no) 73 | (window.attachEvent "onload" runScripts)) 74 | -------------------------------------------------------------------------------- /src/command.jisp: -------------------------------------------------------------------------------- 1 | ; Command line utility 2 | ; Launches interactive REPL 3 | ; Compiles files 4 | ; Mostly copied from CoffeeScript source, bow to Jeremy and team, todo rewrite 5 | 6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7 | 8 | (= fs (require "fs") 9 | path (require "path") 10 | mkdirp (require "mkdirp") 11 | spawn (require "child_process").spawn 12 | exec (require "child_process").exec 13 | EventEmitter (require "events").EventEmitter 14 | jisp (require "./jisp") 15 | utils (require "./utils") 16 | optparse (require "./optparse")) 17 | 18 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Rest ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 19 | 20 | ; Putting more than one backslash directly before a quote breaks our tokeniser, todo fix 21 | (= useWinPathSep (is path.sep ("\\ ".slice 0 1))) 22 | 23 | ; Allow jisp to emit Node.js events 24 | (utils.extend jisp (new EventEmitter)) 25 | 26 | (def printLine line 27 | (process.stdout.write (+ line "\n"))) 28 | 29 | (def printWarn line 30 | (process.stderr.write (+ line "\n"))) 31 | 32 | (def hidden file (/^\.|~$/.test file)) 33 | 34 | ; Startup help banner 35 | (= banner " 36 | Usage: jisp [options] path/to/script.jisp -- [args] 37 | 38 | When called without options, compiles your script and prints the output to stdout.") 39 | 40 | ; List of valid options 41 | (= switches `( 42 | ("-c" "--compile" "compile to JavaScript and save as .js files") 43 | ("-o" "--output [dir]" "set the output directory for compiled JavaScript") 44 | ("-i" "--interactive" "run an interactive jisp REPL (this is the default with no options and arguments)") 45 | ("-v" "--version" "display the version number") 46 | )) 47 | 48 | ; Global objects 49 | (= opts (:) 50 | sources `() 51 | sourceCode `() 52 | notSources (:) 53 | optionParser null) 54 | 55 | ; Run `jisp` by parsing passed options and branching on actions 56 | (= exports.run (def run 57 | (do (parseOptions) 58 | ; Make the REPL CLI use the global context 59 | (= replCliOpts (useGlobal: yes)) 60 | (if opts.version (return (version))) 61 | (if (or opts.interactive (not opts.arguments.length)) 62 | (return ((require "./repl").start replCliOpts))) 63 | (= literals (if opts.run (opts.arguments.splice 1) `()) 64 | process.argv ((process.argv.slice 0 1).concat literals) 65 | process.argv[0] 'jisp') 66 | (if opts.output (= opts.output (path.resolve opts.output))) 67 | (for source opts.arguments 68 | (do (= source (path.resolve source)) 69 | (compilePath source yes source)))))) 70 | 71 | ; Compiles a path, which could be a script or directory. If a directory is passed, recursively compile all '.jisp' files and subdirectories 72 | (def compilePath source topLevel base 73 | (do (if (or (in source sources) 74 | (and (not topLevel) 75 | (or notSources[source] (hidden source)))) 76 | (return)) 77 | (try (= stats (fs.statSync source)) 78 | (catch err (do (if (is err.code "ENOENT") 79 | (do (console.error (+ "File not found:" source)) 80 | (process.exit 1))) 81 | (throw err)))) 82 | (if (stats.isDirectory) 83 | (if (is (path.basename source) "node_modules") 84 | (= notSources[source] yes) 85 | (elif opts.run 86 | (compilePath (findDirectoryIndex source) topLevel base)) 87 | (do (try (= files (fs.readdirSync source)) 88 | (catch err (if (is err.code "ENOENT") 89 | (return) 90 | (throw err)))) 91 | (for file files 92 | (compilePath (path.join source file) no base)))) 93 | (elif (or topLevel (utils.isJisp source)) 94 | (do (sources.push source) 95 | (sourceCode.push null) 96 | (delete notSources[source]) 97 | (try (= code (fs.readFileSync source)) 98 | (catch err (if (is err.code "ENOENT") 99 | return 100 | (throw err)))) 101 | (compileScript source (code.toString) base))) 102 | (= notSources[source] yes)))) 103 | 104 | (def findDirectoryIndex source 105 | (do (for ext jisp.fileExtensions 106 | (do (= index (path.join source (+ "index" ext))) 107 | (try (if ((fs.statSync index).isFile) (return index)) 108 | (catch err (if (not (is err.code "ENOENT")) 109 | (throw err)))))) 110 | (console.error (+ "Missing index.jisp in " source)) 111 | (process.exit 1))) 112 | 113 | 114 | ; Compiles a single source script 115 | ; By default saves into the same directory, changing extension to .js 116 | (def compileScript file input (base null) 117 | (do (= o opts 118 | options (compileOptions file base)) 119 | (try 120 | (do (= t (= task (file: file input: input options: options))) 121 | (jisp.emit "compile" task) 122 | (if o.run 123 | (do (jisp.register) 124 | (jisp.run t.input t.options)) 125 | (do (= compiled (jisp.compile t.input) 126 | t.output compiled) 127 | (jisp.emit "success" task) 128 | (if o.compile 129 | (writeJs base t.file t.output options.jsPath) 130 | (printLine (t.output.trim)))))) 131 | (catch err 132 | (do (jisp.emit "failure" err task) 133 | (if (jisp.listeners "failure").length (return)) 134 | (= message (or err.stack (err.toString))) 135 | (printWarn message) 136 | (process.exit 1)))))) 137 | 138 | ; Attach listeners to compile scripts incoming over stdin and write back to stdout 139 | (def compileStdin 140 | (do (= code "" 141 | stdin (process.openStdin)) 142 | (stdin.on "data" (fn buffer 143 | (if buffer (+= code (buffer.toString))))) 144 | (stdin.on "end" (fn (compileScript null code))))) 145 | 146 | ; If all source files are done being read, concat and compile them together 147 | (= joinTimeout null 148 | compileJoin (fn 149 | (if (not (sourceCode.some (fn code (is code null)))) 150 | (do (clearTimeout joinTimeout) 151 | (= joinTimeout (wait 100 (fn 152 | (compileScript opts.join (sourceCode.join "\n") opts.join)))))))) 153 | 154 | ; Get corresponding output JavaScript path for source file 155 | (def outputPath source base (extension ".js") 156 | (do (= basename (utils.baseFileName source yes useWinPathSep) 157 | srcDir (path.dirname source) 158 | dir (if (not opts.output) 159 | srcDir 160 | (elif (is source base) 161 | opts.output) 162 | (path.join opts.output (path.relative base srcDir)))) 163 | (path.join dir (+ basename extension)))) 164 | 165 | ; Write out JavaScript source file with compiled code. By default writes out in `cwd` as `.js` files with same name, but output dir can be customised with `--output` 166 | (def writeJs base sourcePath js jsPath (do 167 | (= jsDir (path.dirname jsPath) 168 | js js) 169 | (def compile 170 | (if opts.compile (do 171 | (if (<= js.length 0) (= js " ")) 172 | (fs.writeFile jsPath js (fn err 173 | (if err (printLine err.message))))))) 174 | (fs.exists jsDir (fn itExists 175 | (if itExists (compile) (mkdirp jsDir compile)))))) 176 | 177 | ; For prettier timeouts 178 | (def wait milliseconds func 179 | (setTimeout func milliseconds)) 180 | 181 | ; Options parser 182 | (def parseOptions 183 | (= optionParser (new optparse.OptionParser switches banner) 184 | opts (optionParser.parse (process.argv.slice 2)) 185 | o opts 186 | o.compile (or o.compile (is o.output)) 187 | o.run (not o.compile))) 188 | 189 | 190 | ; Compile-time options to pass to compiler 191 | (def compileOptions filename base 192 | (do (= answer (filename: filename)) 193 | (if (not filename) 194 | answer 195 | (if base 196 | (= cwd (process.cwd) 197 | jsPath (outputPath filename base) 198 | jsDir (path.dirname jsPath) 199 | answer (utils.merge answer 200 | (jsPath: jsPath 201 | sourceRoot: (path.relative jsDir cwd) 202 | sourceFiles: `(,(path.relative cwd, filename)) 203 | generatedFile: (utils.baseFileName jsPath no useWinPathSep)))) 204 | (= answer (utils.merge answer 205 | (sourceRoot: "" 206 | sourceFiles: `(,(utils.baseFileName filename no useWinPathSep)) 207 | generatedFile: (+ (utils.baseFileName filename yes useWinPathSep) ".js")))))))) 208 | 209 | (def version 210 | (printLine (+ "jisp version " jisp.version))) -------------------------------------------------------------------------------- /src/functions.jisp: -------------------------------------------------------------------------------- 1 | ; Built-in top-level jisp functions 2 | ; The compiler embeds them into the compiled program 3 | 4 | ; Each function MUST NOT enclose any variables. It must be fully self-sufficient when printed with .toString 5 | ; Meaning, all utilities in this file must be macros, and nothing must be imported 6 | 7 | (= exports.concat (def concat …lists 8 | (do (= _res `()) 9 | (for lst lists 10 | (= _res (_res.concat lst))) 11 | _res))) 12 | 13 | (= exports.list (def list …args `(…args))) 14 | 15 | ; (range ) 16 | ; (range ) ; start is 0 17 | (= exports.range (def range start end 18 | (do (if (?! end) (= end start start 0)) 19 | (while true (if (<= start end) 20 | (do (= a start) (++ start) a) 21 | (break)))))) 22 | -------------------------------------------------------------------------------- /src/index.jisp: -------------------------------------------------------------------------------- 1 | ; Loader for jisp as Node.js library 2 | 3 | (over val key (require "./jisp") 4 | (= exports[key] val)) 5 | -------------------------------------------------------------------------------- /src/lex.jisp: -------------------------------------------------------------------------------- 1 | ; Converts string tokens into native JS objects 2 | ; Desugars syntax shortcuts: 3 | ; quote 4 | ; unquote 5 | ; spread 6 | ; get (.dot and ["bracket"] notation) 7 | ; Throws syntax errors 8 | 9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10 | 11 | (= utils (require "./utils") 12 | pr utils.pr 13 | spr utils.spr 14 | isList utils.isList 15 | isAtom utils.isAtom 16 | isaString utils.isaString 17 | isNum utils.isNum 18 | isRegex utils.isRegex 19 | isIdentifier utils.isIdentifier 20 | isString utils.isString 21 | isKey utils.isKey 22 | isDotName utils.isDotName 23 | isBracketName utils.isBracketName 24 | isBracketString utils.isBracketString 25 | isPropSyntax utils.isPropSyntax) 26 | 27 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 28 | 29 | (def printConditions conditions 30 | (do (for cond (concat conditions) 31 | (if (and (isa cond "function") (? cond.name)) 32 | cond.name 33 | (elif (isList cond) 34 | (printConditions cond)) 35 | (pr cond))) 36 | (.join " "))) 37 | 38 | (def maketest condition 39 | (if (is (typeof condition) "function") 40 | (fn tokens (condition (car tokens))) 41 | (elif (isRegex condition) 42 | (fn tokens (condition.test (car tokens)))) 43 | (elif (isAtom condition) 44 | (fn tokens (is (car tokens) condition))) 45 | (elif (isList condition) ; assume list of tests 46 | (fn tokens 47 | (if (for cond i condition 48 | (if (not ((maketest cond) (tokens.slice i))) 49 | (return false))) 50 | true))) 51 | (throw (Error (+ "can't test against " (pr condition)))))) 52 | 53 | (def demand tokens ...args 54 | ; lexes by the met condition and throws an error if none are met 55 | (do (= conditions `() 56 | modes `()) 57 | (while (> args.length 0) 58 | (do (= condition (args.shift) 59 | mode (args.shift)) 60 | (conditions.push condition) 61 | (modes.push mode) 62 | (= test (maketest condition)) 63 | (if (test tokens) 64 | (return (lex tokens mode))))) 65 | ; todo print prettier error 66 | (= err (if (?! (car tokens)) 67 | (Error "unexpected end of input, probably missing ) ] }") 68 | (Error (+ 69 | "unexpected " (pr (car tokens)) " in possible modes: " 70 | (modes.join " | ") "\n\nTested against: " (printConditions conditions) 71 | "\n\nTokens: " (spr (tokens.slice 0 10)) (if (> tokens.length 10) " ..." " ") )))) 72 | (throw err))) 73 | 74 | (def expect tokens ...args 75 | ; lexes by the met condition and returns undefined if none are met 76 | (while (> args.length 0) 77 | (do (= condition (args.shift) 78 | mode (args.shift)) 79 | (= test (maketest condition)) 80 | (if (test tokens) (return (lex tokens mode)))) 81 | undefined)) 82 | 83 | (def forbid tokens ...args 84 | ; throws an error if one of the conditions is met 85 | (for condition args 86 | (if ((maketest condition) tokens) 87 | (throw (Error (+ "unexpected " (pr (car tokens)))))))) 88 | 89 | (def nextProp tokens 90 | (expect tokens 91 | "[" "property" 92 | isPropSyntax "property")) 93 | 94 | (def grabProperties tokens lexed 95 | (while (= prop (nextProp tokens)) 96 | (if (?! lexed) 97 | (= lexed `("get" prop)) 98 | (= lexed `("get" lexed prop))) 99 | lexed)) 100 | 101 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Main Lexer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 102 | 103 | (def lex tokens (mode "default") 104 | (switch mode 105 | (case "default" ; should only happen once 106 | (do (= lexed `()) 107 | (if (? (= prop (grabProperties tokens))) (lexed.push prop)) 108 | (while (> tokens.length 0) 109 | (lexed.push 110 | (demand tokens 111 | `("(" ":" ")") "emptyhash" 112 | `("(" isKey ":") "hash" 113 | "(" "list" 114 | "`" "quote" 115 | "," "unquote" 116 | "..." "spread" 117 | "…" "spread" 118 | isaString "atom" 119 | undefined "drop"))) 120 | (grabProperties tokens lexed))) 121 | (case "list" 122 | (do (demand tokens "(" "drop") 123 | (= lexed `()) 124 | (if (? (= prop (grabProperties tokens))) (lexed.push prop)) 125 | (while (isnt (car tokens) ")") ; EOF will be caught by demand 126 | (lexed.push 127 | (demand tokens 128 | `("(" ":" ")") "emptyhash" 129 | `("(" isKey ":") "hash" 130 | "(" "list" 131 | "`" "quote" 132 | "," "unquote" 133 | "..." "spread" 134 | "…" "spread" 135 | isaString "atom"))) 136 | (demand tokens ")" "drop") 137 | (grabProperties tokens lexed))) 138 | (case "emptyhash" 139 | (do (demand tokens "(" "drop") 140 | (demand tokens ":" "drop") 141 | (demand tokens ")" "drop") 142 | (grabProperties tokens (:)))) 143 | (case "hash" 144 | (do (= lexed (:)) 145 | (demand tokens "(" "drop") 146 | (while (isnt (car tokens) ")") ; EOF will be caught by demand 147 | (do (= key (demand tokens isKey "key")) 148 | (demand tokens ":" "drop") 149 | (= prop (demand tokens 150 | `("(" ":" ")") "emptyhash" 151 | `("(" isKey ":") "hash" 152 | "(" "list" 153 | "`" "quote" 154 | "," "unquote" 155 | isaString "atom")) 156 | (= lexed[key] prop))) 157 | (demand tokens ")" "drop") 158 | (grabProperties tokens lexed))) 159 | (case "property" 160 | (if (isDotName (car tokens)) 161 | ; don't modify the .dot part whatsoever 162 | (demand tokens isDotName "drop") 163 | (elif (or (isBracketName (car tokens)) 164 | (isBracketString (car tokens))) 165 | (do (demand tokens 166 | isBracketName "drop" 167 | isBracketString "drop") 168 | (.slice 1 -1))) 169 | (do (demand tokens "[" "drop") 170 | (= prop (demand tokens 171 | "(" "list" 172 | "," "quote" 173 | isIdentifier "atom" 174 | isNum "atom" 175 | isString "atom")) 176 | (demand tokens "]" "drop") 177 | prop))) 178 | (case "quote" 179 | (do (demand tokens "`" "drop") 180 | (= lexed `("quote" ,(demand tokens 181 | `("(" ":" ")") "emptyhash" 182 | `("(" isKey ":") "hash" 183 | "(" "list" 184 | "`" "quote" 185 | "," "unquote" 186 | isaString "atom")))) 187 | (grabProperties tokens lexed)) 188 | (case "unquote" 189 | (do (demand tokens "," "drop") 190 | `("unquote" ,(grabProperties tokens (demand tokens 191 | "(" "list" 192 | "`" "quote" 193 | "..." "spread" 194 | "…" "spread" 195 | isIdentifier "atom"))))) 196 | (case "spread" 197 | (do (demand tokens 198 | "..." "drop" 199 | "…" "drop") 200 | `("spread" ,(grabProperties tokens (demand tokens 201 | "(" "list" 202 | "`" "quote" 203 | isIdentifier "atom"))))) 204 | (case "key" 205 | (do (= key (demand tokens isKey "drop")) 206 | (forbid "[" isPropSyntax) 207 | key)) 208 | (case "atom" 209 | (grabProperties tokens (demand tokens isaString "drop"))) 210 | (case "drop" (tokens.shift)) 211 | (throw (Error (+ "unspecified lex mode: " mode))))) 212 | 213 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Export ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 214 | 215 | (= module.exports lex) 216 | -------------------------------------------------------------------------------- /src/macros.jisp: -------------------------------------------------------------------------------- 1 | ; Built-in Macros Module 2 | 3 | ; Default macros to add: 4 | ; (test x (case func0 body) (case func1 body)) -> applies func in each case, 5 | ; expands to series of elifs; tests for equality against literals and for type against undefined. 6 | ; ... 7 | 8 | ; For embedding purposes, macros should not enclose any objects. 9 | ; They must be fully self-sufficient when printed with .toString. 10 | ; Meaning, all utilities in this file must be macros themselves, and nothing must be imported. 11 | ; A possible exception is the macros that can't be referenced by name (like ?!). 12 | 13 | (= utils (require "./utils")) 14 | 15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 16 | 17 | (mac macCheckVar exp 18 | ; a very approximate check if exp is an identifier 19 | (if (and (isa exp "string") 20 | (/^[$#_A-Za-z]{1}$|^[$#_A-Za-z]+[$_\w]*(?:[$_\w](?!\.))+$/.test exp)) 21 | true 22 | (throw Error (+ "expecting valid identifier, got " exp)))) 23 | 24 | (mac macOneArg name rest 25 | `(if (or (?! ,name) (> (get ,rest "length") 0)) 26 | (throw (Error (+ "expecting one argument, got: " ,name ", " ,rest))))) 27 | 28 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 29 | 30 | ; `:` hash table macro 31 | (mac macHash ...args 32 | (if (is args.length 1) 33 | ; runtime hash 34 | `(do (= #_res (:) 35 | #_ref ,(car args)) 36 | (while (> #_ref.length 0) 37 | (= #_res[(#_ref.shift)] (#_ref.shift))) 38 | #_res) 39 | ; compile-time hash 40 | (do (= buffer (:)) 41 | (while (> args.length 0) 42 | (= buffer[(args.shift)] (args.shift))) 43 | buffer))) 44 | 45 | (= exports[":"] macHash) 46 | 47 | ; `::` concat hash table macro 48 | (mac macConcatHash ...args 49 | `(: (concat ,...(for arg args `(spread ,arg))))) 50 | 51 | (= exports["::"] macConcatHash) 52 | 53 | ; `prn`: short alias for console.log 54 | (mac macPrn ...x 55 | `(console.log ,...x)) 56 | 57 | (= exports.prn macPrn) 58 | 59 | ; `car`: x[0] 60 | ; `head`: x[0] 61 | (mac macCar x ...other (do 62 | (macOneArg x other) 63 | `(get ,x 0))) 64 | 65 | (= exports.car macCar) 66 | (= exports.head macCar) 67 | 68 | ; `cdr`: x.slice(1) 69 | ; `tail`: x.slice(1) 70 | (mac macCdr x ...other (do 71 | (macOneArg x other) 72 | `((get ,x "slice") 1))) 73 | 74 | (= exports.cdr macCdr) 75 | (= exports.tail macCdr) 76 | 77 | ; `init`: x.slice(0, -1) 78 | (mac macInit x ...other (do 79 | (macOneArg x other) 80 | `((get ,x "slice") 0 -1))) 81 | 82 | (= exports.init macInit) 83 | 84 | ; `last`: x.slice(-1)[0] 85 | (mac macLast x ...other (do 86 | (macOneArg x other) 87 | `(get ((get ,x "slice") -1) 0))) 88 | 89 | (= exports.last macLast) 90 | 91 | ; `let`: self-executing lambda with auto-passed arguments 92 | (mac macLet ...args body (do 93 | (if (isnt (% args.length 2) 0) 94 | (throw Error (+ "expecting an even number of arguments, got " args.length))) 95 | (if (?! body) (= body `())) 96 | (= names `() 97 | callArgs `()) 98 | (while (> args.length 0) 99 | (do (= name (args.shift)) 100 | (if (macCheckVar name) 101 | (names.push name)) 102 | (callArgs.push (args.shift)))) 103 | `((fn ,...names ,body) ,...callArgs))) 104 | 105 | (= exports.let macLet) 106 | 107 | ; helper for `?` 108 | ; takes a form and makes an array of property references, starting with base object 109 | ; with existence check wrapped around each 110 | (def compartmentaliseExist form 111 | (if (and (utils.isList form) (is (car form) "get")) 112 | (list ...(compartmentaliseExist form[1]) `("isnta" form "'undefined'")) 113 | (elif (and (isa form "string") (utils.isIdentifier form) (not (utils.isSpecialValueStr form))) 114 | (for val i (= split (utils.splitName form)) 115 | `("isnta" ,(do (split.slice 0 (+ i 1)) (.join "")) "'undefined'"))) 116 | `(("isnta" form "'undefined'")))) 117 | 118 | ; `?`: existence check 119 | ; (not (isa x "undefined")) 120 | ; (or (? x) (? y) ...) 121 | (mac macExist ...values (do 122 | (= elements (for value values (do 123 | (= comp (compartmentaliseExist value)) 124 | (if (> comp.length 1) 125 | `(and ,...comp) 126 | (car comp))))) 127 | (if (> elements.length 1) 128 | `(or ,...elements) 129 | (car elements)))) 130 | 131 | (= exports["?"] macExist) 132 | 133 | ; helper for `?!` 134 | ; takes a form and makes an array of property references, starting with base object 135 | ; with inexistence check wrapped around each 136 | (def compartmentaliseNotExist form 137 | (if (and (utils.isList form) (is (car form) "get")) 138 | (list ...(compartmentaliseNotExist form[1]) `("isa" form "'undefined'")) 139 | (elif (and (isa form "string") (utils.isIdentifier form) (not (utils.isSpecialValueStr form))) 140 | (for val i (= split (utils.splitName form)) 141 | `("isa" ,(do (split.slice 0 (+ i 1)) (.join "")) "'undefined'"))) 142 | `(("isa" form "'undefined'")))) 143 | 144 | ; `?!`: inexistence check 145 | ; (isa x "undefined") 146 | ; (or (?! x) (?! y) ...) 147 | (mac macNotExist ...values (do 148 | (= elements (for value values (do 149 | (= comp (compartmentaliseNotExist value)) 150 | (if (> comp.length 1) 151 | `(or ,...comp) 152 | (car comp))))) 153 | (if (> elements.length 1) 154 | `(and ,...elements) 155 | (car elements)))) 156 | 157 | (= exports["?!"] macNotExist) 158 | 159 | ; `isa`: (is (typeof x) y) 160 | (mac macIsA obj ...types 161 | `(is (typeof ,obj) ,...types)) 162 | 163 | (= exports.isa macIsA) 164 | 165 | ; `isnta`: (isnt (typeof x) y) 166 | (mac macIsNa obj ...types 167 | `(isnt (typeof ,obj) ,...types)) 168 | 169 | (= exports.isnta macIsNa) 170 | 171 | ; `any`: picks first existing value 172 | (mac macAny ...values (do 173 | (= elements (for value values 174 | `(and (? ,value) ,value))) 175 | (if (> elements.length 1) 176 | `(or ,...elements) 177 | (car elements)))) 178 | 179 | (= exports.any macAny) 180 | -------------------------------------------------------------------------------- /src/operators.jisp: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | 3 | (= utils (require "./utils") 4 | pr utils.pr 5 | spr utils.spr 6 | render utils.render 7 | isIdentifier utils.isIdentifier 8 | assertForm utils.assertForm) 9 | 10 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 11 | 12 | (def makeop op zv (min 0) (max Infinity) (drop no) 13 | ; 14 | (fn args innerType 15 | (if (assertForm args min max) 16 | (if (is args.length 0) 17 | (pr zv) 18 | (elif (and (is args.length 1) (? zv)) 19 | (do (= res (+ zv op (spr args))) 20 | ; extra parens for precedence if more operators await 21 | (if (and innerType (isnt innerType "parens")) 22 | (= res (+ "(" res ")"))) 23 | res)) 24 | (elif (and (is args.length 1) drop) 25 | (spr args)) 26 | (elif (is args.length 1) 27 | (+ op (spr args))) 28 | (do (for arg i args (= args[i] (pr arg))) 29 | (= res (args.join (+ " " op " "))) 30 | ; extra parens for precedence if more operators await 31 | (if (and innerType (isnt innerType "parens")) 32 | (= res (+ "(" res ")"))) 33 | res))))) 34 | 35 | (def makesing op 36 | (fn args innerType 37 | (if (assertForm args 1 1) 38 | (+ op " " (spr args))))) 39 | 40 | (def reserved word (throw (Error (+ "keyword " word " is reserved")))) 41 | 42 | (def makestate op (min 0) (max Infinity) 43 | ; For 'pure statement' keywords that give an error when trying to assign 44 | (fn args innerType 45 | (if (assertForm args min max) 46 | (+ op " " (spr args)) "undefined"))) 47 | 48 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Operator Generators ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 49 | 50 | (= operators ( 51 | ; Replacing jisp functions with JS operators and keywords 52 | ; ToDo infinite arguments where possible 53 | ; (not a b c) -> (and (not a) (not b) (not c)) 54 | 55 | ; arithmetic 56 | "++": (fn args innerType 57 | (if (assertForm args 1 1) 58 | (if (not (isIdentifier args[0])) 59 | (throw (Error "expecting identifier, got " (spr args))) 60 | (+ "++" (spr args))))) 61 | "--": (fn args innerType 62 | (if (assertForm args 1 1) 63 | (if (not (isIdentifier args[0])) 64 | (throw (Error "expecting identifier, got " (spr args))) 65 | (+ "--" (spr args))))) 66 | ; logical 67 | "is": (fn args innerType 68 | (if (is args.length 0) 69 | true 70 | (elif (is args.length 1) 71 | (+ "!!" (spr args))) 72 | (do (= subj (args.shift)) 73 | (= res (do (for arg args (+ (pr subj) " === " (pr arg))) 74 | (.join " || "))) 75 | (if (and innerType (isnt innerType "parens")) 76 | (= res (+ "(" res ")"))) 77 | res))) 78 | "isnt": (fn args innerType 79 | (if (is args.length 0) 80 | false 81 | (elif (is args.length 1) 82 | (+ "!" (spr args))) 83 | (do (= subj (args.shift)) 84 | (= res (do (for arg args (+ (pr subj) " !== " (pr arg))) 85 | (.join " && "))) 86 | (if (and innerType (isnt innerType "parens")) 87 | (= res (+ "(" res ")"))) 88 | res))) 89 | "or": (makeop "||" undefined 1 Infinity yes) ; single arg returns itself 90 | "and": (makeop "&&" undefined 1 Infinity yes) ; single arg returns itself 91 | ; keywords 92 | "in": (fn args innerType 93 | ; todo more than 2 args (concat / spread?) 94 | (if (assertForm args 2 2) 95 | (do (= res (+ "[].indexOf.call(" (pr args[1]) ", " (pr (car args)) ") >= 0")) 96 | (if (and innerType (isnt innerType "parens")) 97 | (= res (+ "(" res ")"))) 98 | res))) 99 | "of": (makeop "in" undefined 2 2) 100 | "new": (fn args innerType 101 | (if (assertForm args 1) 102 | (+ "new " (pr (args.shift)) "(" (spr args) ")"))) 103 | ; reserved 104 | ; "var" -- throws compile error without var, todo fix 105 | ; "class" 106 | "function": (fn (reserved "function")) 107 | "with": (fn (reserved "with")) 108 | )) 109 | 110 | (= singops `( 111 | ("not" "!") ("~" "~") ("delete" "delete") ("typeof" "typeof") ("!!" "!!") 112 | )) 113 | 114 | (for op singops (= operators[op[0]] (makesing op[1]))) 115 | 116 | (= ops `( 117 | ; todo un-retardify chained comparisons 118 | ; in JS, 3 < 2 < 1 produces true (facepalm) 119 | ; todo ops like += should take multiple ars and compile into one += and multiple + 120 | ; arithmetic 121 | ("+" undefined 1 Infinity yes) ("-" undefined 1) ("*" 1) ("/" 1) ("%" undefined 1) 122 | ; logical 123 | ("==" "is") ("===" "is") ("!=" "isnt") 124 | ("!==" "isnt") ("&&" "and") ("||" "or") ("!" "not") 125 | ; comparison 126 | (">" undefined 2) ("<" undefined 2) 127 | (">=" undefined 2) ("<=" undefined 2) 128 | ; bitwise 129 | ("&" undefined 2) ("|" undefined 2) ("^" undefined 2) 130 | ("<<" undefined 2) (">>" undefined 2) (">>>" undefined 2) 131 | ; assignment 132 | ("+=" undefined 2) ("-=" undefined 2) ("*=" undefined 2) 133 | ("/=" undefined 2) ("%=" undefined 2) ("<<=" undefined 2) 134 | (">>=" undefined 2) (">>>=" undefined 2) ("&=" undefined 2) 135 | ("^=" undefined 2) ("|=" undefined 2) 136 | ; words and keywords 137 | ("instanceof" undefined 2 2) 138 | ; other 139 | ("," undefined 2 2) ; bugs out due to lexer dropping empty cells 140 | )) 141 | 142 | (for op ops 143 | (if (is (typeof op[1]) "string") 144 | (= operators[op[0]] operators[op[1]]) 145 | (= operators[op[0]] (makeop ...op)))) 146 | 147 | (= stateops `( 148 | ("return" 0 1) ("break" 0 1) ("continue" 0 0) ("throw" 1 1) 149 | )) 150 | 151 | (for op stateops (= operators[op[0]] (makestate op[0]))) 152 | 153 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Export ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 154 | 155 | (= exports.operators operators) 156 | 157 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Operator Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 158 | 159 | ; When operators like > are passed around, the compiler checks against 160 | ; the opFuncs store. If it has an element by that name, that function 161 | ; is hoisted and embedded in compiled JavaScript by calling .toString 162 | ; on it. References in compiled code are renamed into the .name 163 | ; property of the corresponding opFuncs element. 164 | 165 | ; This is unfinished. ToDo implement. 166 | 167 | (mac macMakeOp name operator zeroValue 168 | ; 169 | `(def ,name ...args (do 170 | ; included if zeroValue was passed 171 | ,(if (? zeroValue) 172 | `(args.unshift ,zeroValue)) 173 | ; included always 174 | (if (is args.length 0) 175 | ,zeroValue ; defaults to undefined 176 | (args.reduce {,operator #0 #1}))))) 177 | 178 | (= opFuncs (:)) 179 | 180 | ; Before we start putting these into opFuncs, main compiler needs to 181 | ; learn to only check for opFuncs when operator is not first in list 182 | 183 | (macMakeOp add + 0) 184 | (macMakeOp sub - 0) 185 | (macMakeOp mul * 1) 186 | (macMakeOp div / 1) 187 | 188 | ; (console.log (div 10)) 189 | ; (console.log (add.toString)) 190 | 191 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Export ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 192 | 193 | (= exports.opFuncs opFuncs) 194 | -------------------------------------------------------------------------------- /src/optparse.jisp: -------------------------------------------------------------------------------- 1 | ; Copied from CoffeeScript source 2 | ; ToDo rewrite 3 | 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5 | 6 | (= repeat (require "./utils").repeat) 7 | 8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Option Parser ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 9 | 10 | ; OptionParser class to parse option flags from command line 11 | 12 | (= exports.OptionParser (= OptionParser ((fn (do 13 | 14 | (def OptionParser rules banner 15 | (do (= this.banner banner 16 | this.rules (buildRules rules)) 17 | this)) ; necessary for prototyping to work 18 | 19 | (= OptionParser.prototype.parse (fn args (do 20 | (= options (arguments: `()) 21 | skippingArgument no 22 | originalArgs args 23 | args (normaliseArguments args)) 24 | (for arg i args (do 25 | (if skippingArgument (do 26 | (= skippingArgument no) 27 | continue)) 28 | (if (is arg "--") (do 29 | (= pos (originalArgs.indexOf "--") 30 | options.arguments (options.arguments.concat (originalArgs.slice (+ pos 1)))) 31 | break)) 32 | (= isOption (is (or (arg.match long_flag) 33 | (arg.match short_flag)))) 34 | (= seenNonOptionArg (> options.arguments.length 0)) 35 | (if (not seenNonOptionArg) (do 36 | (= matchedRule no) 37 | (for rule this.rules 38 | (if (is arg rule.shortFlag rule.longFlag) (do 39 | (= value true) 40 | (if rule.hasArgument 41 | (= skippingArgument yes 42 | value args[(+ i 1)])) 43 | (= options[rule.name] (if rule.isList 44 | ((or options[rule.name] `()).concat value) 45 | value)) 46 | (= matchedRule yes) 47 | break))) 48 | (if (and isOption (not matchedRule)) 49 | (throw (new Error (+ "unrecognised option: " arg)))))) 50 | (if (or seenNonOptionArg (not isOption)) 51 | (options.arguments.push arg)))) 52 | options))) 53 | 54 | ; Return help text for this OptionParser 55 | (= OptionParser.prototype.help (fn (do 56 | (= lines `()) 57 | (if this.banner (lines.unshift (+ this.banner "\n"))) 58 | (for rule this.rules (do 59 | (= spaces (- 15 rule.longFlag.length) 60 | spaces (if (> spaces 0) (repeat " " spaces) "") 61 | letPart (if rule.shortFlag (+ rule.shortFlag ", ") " ")) 62 | (lines.push (+ " " letPart rule.longFlag spaces rule.description)))) 63 | (+ "\n" (lines.join "\n") "\n")))) 64 | 65 | OptionParser 66 | 67 | ))))) 68 | 69 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 70 | 71 | (= long_flag /^(--\w[\w\-]*)/ 72 | short_flag /^(-\w)$/ 73 | multi_flag /^-(\w{2,})/ 74 | optional /\[(\w+(\*?))\]/) 75 | 76 | ; Build and return list of option rules 77 | ; If optional `short-flag` unspecified, pad with `null` 78 | ; (def buildRules rules 79 | ; (do (console.log "-- rules:" rules) 80 | ; (for tuple rules 81 | ; (do (console.log "--- rules still:" rules) 82 | ; (if (< tuple.length 3) (tuple.unshift null)) 83 | ; (console.log "-- rule tuple:" tuple) 84 | ; (buildRule ...tuple))))) 85 | 86 | ; Build and return list of option rules 87 | ; If optional `short-flag` unspecified, pad with `null` 88 | (def buildRules rules 89 | (for tuple rules 90 | (do (if (< tuple.length 3) (tuple.unshift null)) 91 | (buildRule ...tuple)))) 92 | 93 | ; Build rule from `-o` short flag, `--output [dir]` long flag, and option description 94 | (def buildRule shortFlag longFlag description (options (:)) 95 | (do (= match (longFlag.match optional) 96 | longFlag (longFlag.match long_flag)[1]) 97 | (name: (longFlag.substr 2) 98 | shortFlag: shortFlag 99 | longFlag: longFlag 100 | description: description 101 | hasArgument: (is (and match match[1])) 102 | isList: (is (and match match[2]))))) 103 | 104 | ; Normalise arguments by expanding merged flags into multiple flags 105 | ; This allows to have `-wl` be same as `--watch --lint` (even though jisp doesn't have these options...) 106 | (def normaliseArguments args 107 | (do (= args (args.slice 0) 108 | result `()) 109 | (for arg args 110 | (if (= match (arg.match multi_flag)) 111 | (for l (match[1].split "") 112 | (result.push (+ "-" l))) 113 | (result.push arg))) 114 | result)) 115 | -------------------------------------------------------------------------------- /src/parse.jisp: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | 3 | (= utils (require "./utils")) 4 | 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Parser ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | 7 | (= module.exports (def parse form 8 | (if (utils.isList form) 9 | (do (for val i form (= form[i] (parse val))) 10 | form) 11 | (elif (utils.isHash form) 12 | (do (over val key form (= form[key] (parse val))) 13 | form)) 14 | (do (= form (utils.typify form)) 15 | (if (/^#(\d+)/.test form) 16 | (form.replace /^#(\d+)/ "arguments[$1]") 17 | form))))) 18 | -------------------------------------------------------------------------------- /src/register.jisp: -------------------------------------------------------------------------------- 1 | ; Mostly copied from CoffeeScript 1.7.1 source 2 | 3 | (= child_process (require "child_process") 4 | path (require "path") 5 | utils (require "./utils") 6 | jisp (require "./jisp")) 7 | 8 | ; Load and run a jisp file for Node, stripping `BOM`s 9 | (def loadFile module filename 10 | (module._compile (jisp.compileFile filename) filename)) 11 | 12 | ; If the installed version of Node supports `require.extensions`, register as an extension 13 | (if require.extensions 14 | (for ext jisp.fileExtensions 15 | (= require.extensions[ext] loadFile))) 16 | 17 | ; If we're on Node, patch `child_process.fork` so our scripts can fork both jisp and JS files 18 | ; Not sure if this is relevant for jisp 19 | ; ToDo account for different jisp `bin`s and paths 20 | ; (if child_process 21 | ; (= fork child_process.fork 22 | ; binary (require.resolve "../../bin/jisp") 23 | ; child_process.fork 24 | ; (fn path args options 25 | ; (do (if (utils.isJisp path) 26 | ; (do (if (not (Array.isArray args)) 27 | ; (= options (or args (:)) 28 | ; args `())) 29 | ; (= args (`(path).concat args) 30 | ; path binary))) 31 | ; (fork path args options))))) 32 | -------------------------------------------------------------------------------- /src/repl.jisp: -------------------------------------------------------------------------------- 1 | ; Mostly borrowed from CoffeeScript source, multiline customised 2 | 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4 | 5 | (= vm (require "vm") 6 | nodeREPL (require "repl") 7 | jisp (require "./jisp")) 8 | 9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10 | 11 | (= replDefaults ( 12 | useGlobal: yes 13 | prompt: "jisp> " 14 | eval: (fn input context filename cb 15 | (do ; XXX: multiline hack 16 | (= input (input.replace /\uFF00/g "\n") 17 | ; Node input arrives wrapped in ( \n), unwrap 18 | input (input.replace /^\(([^]*)\n\)$/g "$1")) 19 | (try (do (= js (jisp.compile input (wrap: no repl: yes))) 20 | (console.log "-- compiled:") 21 | (console.log js) 22 | (console.log "-- executing:") 23 | (= result (vm.runInThisContext js filename)) 24 | (cb null result)) 25 | (catch err (cb err))))))) 26 | 27 | (def enableMultiline repl 28 | ; SUPER UGLY but works, fix later 29 | ; BUG: counts parens inside strings and regexes, todo fix 30 | ; BUG: hangs on multiline with unclosed {, infinite loop somewhere 31 | (do (= rli repl.rli 32 | inputStream repl.inputStream 33 | outputStream repl.outputStream 34 | origPrompt (if (? repl._prompt) repl._prompt repl.prompt) 35 | multiline (enabled: no 36 | prompt: (origPrompt.replace /^[^>\s]*>?/ (fn x (x.replace /./g "."))) 37 | buffer: "") 38 | ; proxy line listener 39 | lineListener (car (rli.listeners "line"))) 40 | (rli.removeListener "line" lineListener) 41 | (rli.on "line" (fn cmd 42 | (if multiline.enabled 43 | (do (+= multiline.buffer (+ cmd "\n")) 44 | (= opened (if (? (= m (multiline.buffer.match /\(/g))) 45 | m.length 0) 46 | closed (if (? (= m (multiline.buffer.match /\)/g))) 47 | m.length 0)) 48 | (if (> opened closed) 49 | (do (rli.setPrompt multiline.prompt) 50 | (rli.prompt true)) 51 | (do (= multiline.enabled no 52 | multiline.buffer (multiline.buffer.replace /\n/g "\uFF00")) 53 | (rli.emit "line" multiline.buffer) 54 | (= multiline.buffer "") 55 | (rli.setPrompt origPrompt) 56 | (rli.prompt true)))) 57 | (do (= opened (if (isa (= m (cmd.match /\(/g)) "string") m.length 0) 58 | closed (if (isa (= m (cmd.match /\)/g)) "string") m.length 0)) 59 | (if (> opened closed) 60 | (do (= multiline.enabled yes) 61 | (+= multiline.buffer (+ cmd "\n")) 62 | (rli.setPrompt multiline.prompt) 63 | (rli.prompt true)) 64 | (lineListener cmd)))))))) 65 | 66 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Export ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 67 | 68 | (= exports.start (= start (fn 69 | (do (= repl (nodeREPL.start replDefaults)) 70 | (repl.on "exit" (fn (repl.outputStream.write "\n"))) 71 | (enableMultiline repl) 72 | repl)))) 73 | -------------------------------------------------------------------------------- /src/tokenise.jisp: -------------------------------------------------------------------------------- 1 | ; Turns a string into a flat array of tokens, split by delimiters and whitespace 2 | 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4 | 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Regexes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | 7 | (= tokens `() ;#` 8 | recode /^[^]*?(?=;.*[\n\r]?|""|"[^]*?(?:[^\\]")|''|'[^]*?(?:[^\\]')|\/[^\s]+\/[\w]*)/ 9 | ;# ^ matches until first comment, '-string, "-string, or regex 10 | recomment /^;.*[\n\r]?/ ; first comment 11 | redstring /^""|^"[^]*?(?:[^\\]")[^\s):\[\]\{\}]*/ ; first " string + data until delimiter 12 | resstring /^''|^'[^]*?(?:[^\\]')[^\s):\[\]\{\}]*/ ; first ' string + data until delimiter 13 | rereg /^\/[^\s]+\/[\w]*[^\s)]*/) ; first regex + data until delimiter 14 | 15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 16 | 17 | (def grate str 18 | (do str 19 | (.replace /;.*$/gm "") ; drop comments if any 20 | (.replace /\{/g "(fn (") ; desugar lambdas 21 | (.replace /\}/g "))") ; desugar lambdas 22 | (.replace /\(/g " ( ") 23 | (.replace /\)/g " ) ") 24 | (.replace /\[$/g " [ ") 25 | (.replace /\['/g " [ '") 26 | (.replace /\["/g ' [ "') 27 | (.replace /'\]/g "' ] ") 28 | (.replace /"\]/g '" ] ') 29 | (.replace /\[[\s]*\(/g " [ ( ") 30 | (.replace /\)[\s]*\]/g " ) ] ") 31 | (.replace /([^:]):(?!\:)/g "$1 : ") 32 | (.replace /`/g " ` ") 33 | (.replace /,/g " , ") 34 | (.replace /\.\.\./g " ... ") 35 | (.replace /…/g " … ") 36 | (.trim) 37 | (.split /\s+/))) 38 | 39 | (def concatNewLines str (str.replace /\n|\n\r/g "\\n")) 40 | 41 | (def match str re 42 | (if (and (= mask (str.match re)) 43 | (> (car mask).length 0)) 44 | (car mask) 45 | null)) 46 | 47 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Tokeniser ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 48 | 49 | (def tokenise str 50 | (do (= tokens `()) 51 | (while (> (= str (str.trim)).length 0) 52 | (if (= mask (match str recode)) 53 | (do (tokens.push …(grate mask)) 54 | (= str (str.replace recode ""))) 55 | (elif (= mask (match str recomment)) 56 | (= str (str.replace recomment ""))) 57 | (elif (= mask (match str redstring)) 58 | (do (tokens.push (concatNewLines mask)) 59 | (= str (str.replace redstring "")))) 60 | (elif (= mask (match str resstring)) 61 | (do (tokens.push (concatNewLines mask)) 62 | (= str (str.replace resstring "")))) 63 | (elif (= mask (match str rereg)) 64 | (do (tokens.push mask) 65 | (= str (str.replace rereg "")))) 66 | (do (tokens.push …(grate str)) 67 | (= str "")))) 68 | (tokens.filter (fn x (and (? x) (isnt x "" undefined null)))))) 69 | 70 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Export ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 71 | 72 | (= module.exports tokenise) 73 | -------------------------------------------------------------------------------- /src/uniq.jisp: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Dependencies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | 3 | (= utils (require "./utils")) 4 | 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Prototype ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | 7 | (def Uniq uniq store (do 8 | (= this.parent uniq 9 | this.store (:)) 10 | (if store (over name of store 11 | (= this.store[of] name))) 12 | this)) 13 | 14 | (= Uniq.prototype.find (fn func (do 15 | (= uniq this) 16 | (while (? uniq) 17 | (if (= ref (func.call uniq)) (break) 18 | (= uniq uniq.parent)) ref)))) 19 | 20 | (= Uniq.prototype.findOut (fn func 21 | (if (? this.parent) (this.parent.find func)))) 22 | 23 | (= Uniq.prototype.has (fn key (in key (Object.keys this.store)))) 24 | 25 | (= Uniq.prototype.conflict (fn key 26 | (this.findOut {this.has key}))) 27 | 28 | (= Uniq.prototype.resolve (fn key (do 29 | (= oldkey key) 30 | (while (this.conflict key) 31 | (= key (utils.plusname key))) 32 | (= this.store[key] (= this.store[oldkey] (fn name 33 | (name.replace (RegExp (+ "^" oldkey)) key))))))) 34 | 35 | (= Uniq.prototype.checkAndReplace (fn name (do 36 | ; get service part of name 37 | (= key (utils.getServicePart name)) 38 | ; check if we have already defined replacement, define if not 39 | (if (not (this.has key)) 40 | (this.resolve key)) 41 | ; replace and return 42 | (this.store[key] name)))) 43 | 44 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Export ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 45 | 46 | (= module.exports Uniq) 47 | -------------------------------------------------------------------------------- /src/utils.jisp: -------------------------------------------------------------------------------- 1 | ; Utils for other modules 2 | ; Got bloated, todo refactor 3 | 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; For Compiler ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5 | 6 | (= exports.keywords (= keywords `( 7 | "return" "break" "continue" "throw" "delete" 8 | ))) 9 | 10 | (= exports.kwtest (def kwtest str (do 11 | (= re (RegExp (do (for kw keywords 12 | (+ "^" kw " |^" kw "$")) 13 | (.join "|")))) 14 | (re.test str)))) 15 | 16 | (= exports.specialValues (= specialValues `( 17 | "undefined" "null" "true" "false" "yes" "no" "Infinity" "NaN" "this" 18 | ))) 19 | 20 | (= exports.isSpecialValueStr (def isSpecialValueStr str 21 | (in str specialValues))) 22 | 23 | (= exports.isSpecialValue (def isSpecialValue form 24 | (or (isa form "undefined") 25 | (is form null) 26 | (and (isa form "number") (isNaN form)) 27 | (is form Infinity) 28 | (isa form "boolean")))) 29 | 30 | ;------------------------------- Composite Types ------------------------------- 31 | 32 | (= exports.isAtom (def isAtom form 33 | (or (is form undefined null) 34 | (/^\/[^\s\/]+\/[\w]*$/.test form) 35 | (isa form "number" "string" "boolean")))) 36 | 37 | (= exports.isaString (def isaString form 38 | (isa form "string"))) 39 | 40 | (= exports.isList (def isList form 41 | (Array.isArray form))) 42 | 43 | (= exports.isHash (def isHash form 44 | (and (not (isAtom form)) 45 | (not (isList form)) 46 | (not (isa form "function"))))) 47 | 48 | (= exports.isBlankObject (def isBlankObject form 49 | (try (is (Object.keys form).length 0) 50 | false))) 51 | 52 | (= exports.isKey (def isKey form 53 | (and (isAtom form) (or (isString form) 54 | (isIdentifier form) 55 | (isNum form))))) 56 | 57 | (= exports.isService (def isServiceName form 58 | (and (isa form "string") 59 | (/^#/.test form) 60 | (not (/^#$|^#\d|^#\.|^#\[/.test form))))) 61 | 62 | (= exports.getServicePart (def getServicePart form 63 | (car (form.match /^#[^.[]+/)))) 64 | 65 | ;-------------------------------- Simple Types -------------------------------- 66 | 67 | (= exports.isVarName (def isVarName form 68 | ; matches pure variable names without property notation 69 | (and (isAtom form) (/^[$#_A-Za-z]{1}$|^[$#_A-Za-z]+[$_\w]*(?:[$_\w](?!\.))+$/.test form)))) 70 | 71 | (= exports.isIdentifier (def isIdentifier form 72 | ; matches any identifier, including with .dot and [bracket] and ["string bracket"] notation, unless it has an expression in brackets 73 | ; intentionally allows parentheses, for functions returning pointers to objects 74 | (and (isAtom form) 75 | (/^[$#_A-Za-z]{1}[$_\w()]*((\.[$#_A-Za-z]{1}[$_\w()]*)|(\[[$_.\w()\[\]]+\])|(\['.*'\])|(\[".*"\]))*$/.test form)))) 76 | 77 | (= exports.isString (def isString form 78 | (and (isAtom form) (/^".*"$|^'.*'$/.test form)))) 79 | 80 | (= exports.isRegex (def isRegex form 81 | ; passes regexes and regexes+stuff 82 | (and (isAtom form) (/^\/[^\s]+\/[\w]*[^\s)]*/.test form)))) 83 | 84 | (= exports.isNum (def isNum form 85 | (and (isAtom form) (isa (typify form) "number")))) 86 | 87 | (= exports.isPrimitive (def isPrimitive form 88 | (or (isRegex form) 89 | (isNum form) 90 | (is form undefined null yes no)))) 91 | 92 | (= exports.isArgHash (def isArgHash form 93 | (and (isAtom form) (/^#[\d]+$/.test form)))) 94 | 95 | (= exports.isArgsHash (def isArgsHash form 96 | (and (isAtom form) (/^#$/.test form)))) 97 | 98 | (= exports.isArgHashNotation (def isArgHashNotation form 99 | (or (isArgHash form) 100 | (isArgsHash form)))) 101 | 102 | ;----------------- Property Syntax — Dot and Bracket Notation ----------------- 103 | 104 | (= exports.isDotName (def isDotName form 105 | (and (isAtom form) (/^\.[$#_A-Za-z]{1}$|^\.[$#_A-Za-z]+[$_.\w]*(?:[$_\w](?!\.))+$/.test form)))) 106 | 107 | (= exports.isBracketName (def isBracketName form 108 | (and (isAtom form) (or (/^\[[$#_A-Za-z]{1}\]$|^\[[$#_A-Za-z]+[$_.\w()]*(?:[$_\w()](?!\.))+\]$/.test form) 109 | (/^\[[\d]+\]/.test form))))) 110 | 111 | (= exports.isBracketString (def isBracketString form 112 | (and (isAtom form) (/^\[".*"\]$|^\['.*'\]$/.test form)))) 113 | 114 | (= exports.isPropSyntax (def isPropSyntax form 115 | (and (isAtom form) (or (isDotName form) 116 | (isBracketName form) 117 | (isBracketString form))))) 118 | 119 | ;----------------------------------- Other ------------------------------------ 120 | 121 | (= exports.typify (def typify form 122 | (if (not (isAtom form)) 123 | (throw (Error (+ "expecting atom, got " (pr form)))) 124 | (elif (isBlankObject form) form) 125 | (elif (isa form "undefined") undefined) 126 | (elif (is form "null") null) 127 | (elif (is form "true" "yes") true) 128 | (elif (is form "false" "no") false) 129 | (elif (not (isNaN (Number form))) (Number form)) 130 | (elif (isRegex form) form) 131 | (elif (isa form "string") form) 132 | (throw (Error (+ "syntax error: unrecognised type of " (pr form))))))) 133 | 134 | (= exports.assertForm (def assertForm form (min 0) (max Infinity) first 135 | (if (not (isList form)) 136 | (throw (Error (+ "expecting list, got " form))) 137 | (elif (not (and (>= form.length min) (<= form.length max))) 138 | (throw (Error (+ "expecting between " min " and " max " arguments, got " form.length ": " (pr form))))) 139 | (elif (and (? first) (isnt form[0] first)) 140 | (throw (Error (+ "expecting " (pr first) " as first element, got " (pr form[0]))))) 141 | form))) 142 | 143 | (= exports.assertExp (def assertExp exp test (expect "valid expression") 144 | (if (test exp) true 145 | (throw (Error (+ "expecting " (pr expect) ", got " (pr exp))))))) 146 | 147 | ; splits an identifier into a list of substrings, splitting off all property notations 148 | (= exports.splitName (def splitName name (do 149 | (= re /\.[$_\w]+$|\[[^\[\]]+\]$|\[.+\]$/ 150 | reDot /\.[$_\w]+$/ ; .dot notation on end 151 | reBracket /\[[^\[\]]+\]$/ ; [bracket] notation on end 152 | reBracketGreedy /\[.+\]$/) ; [bracket[stuff]] notation on end 153 | (= res `()) 154 | (while (name.match re) (do 155 | ; find matching regex 156 | (= reg (or (and (name.match reDot) reDot) 157 | (and (name.match reBracket) reBracket) 158 | (and (name.match reBracketGreedy) reBracketGreedy))) 159 | (res.unshift (car (name.match reg))) 160 | (= name (name.replace reg "")))) 161 | (res.unshift name) 162 | res))) 163 | 164 | ; Adds or increments number at end of string 165 | (= exports.plusname (def plusname name 166 | (if (isNaN (Number (last name))) 167 | (+ name 0) 168 | (+ (init name) (+ 1 (Number (last name))))))) 169 | 170 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; For Rendering ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 171 | 172 | ; Pretty-print 173 | ; Turns data objects into pretty-looking strings, with proper [ ] and { } delimiters for arrays and hash tables 174 | (= exports.pr (def pr item 175 | (if (isAtom item) 176 | (do (+ "" item) 177 | (.replace /;$/ "")) ; remove trailing semicolon, if any 178 | (elif (isHash item) 179 | (do (= res "") 180 | (over val key item 181 | (+= res (+ key ": " (pr val) ", "))) 182 | (+ "{ " (res.slice 0 -2) " }"))) 183 | (elif (isList item) 184 | (do (= res "") 185 | (for val item 186 | (+= res (+ (pr val) ", "))) 187 | (+ "[ " (res.slice 0 -2) " ]"))) 188 | ; (throw (Error (+ "unrecognised kind of data object: " item)))))) 189 | (+ "" item)))) 190 | 191 | ; Turns an array into a string without [ ] delimiters: [1, 2, 3] -> 1, 2, 3 192 | ; For printing-spreading 193 | (= exports.spr (def spr item 194 | (if (isList item) 195 | (do (= res "") 196 | (for val item 197 | (+= res (+ (pr val) ", "))) 198 | (res.slice 0 (- res.length 2))) 199 | (throw (Error "can only print-spread lists"))))) 200 | 201 | ; Turns an array of strings into one rendered string 202 | (= exports.render (def render buffer 203 | (do (for exp i buffer 204 | ; `undefined`, "", and `() don't render at all 205 | (if (or (and (isList exp) (is exp.length 0)) 206 | (isa exp "undefined") 207 | (is exp "")) 208 | (= buffer[i] undefined) ; won't be displayed after `join`ing 209 | (do (= res (if (isa exp "string") 210 | (exp.trim) 211 | (pr exp))) 212 | ; hash tables and lambdas need extra parens when on their own line 213 | (if (or (isHash exp) 214 | (/^function\s*\(/.test res)) 215 | (= res (+ "(" res ")"))) 216 | ; add semicolons to forms that need them 217 | (if (not (/:$|\}$|;$/.test (res.slice -1))) 218 | (+= res ";")) 219 | (= buffer[i] res)))) 220 | (buffer.join " ") 221 | (.trim)))) 222 | 223 | ; Removes all pairs of parentheses around a string 224 | ; MUST NOT be applied to strings compiled from multiple expressions, only a SINGLE expression 225 | (= exports.deParenthesise (def deParenthesise str 226 | (if (isa str "string") 227 | (while (and (str.match /^\({1}/) 228 | (str.match /\){1}$/)) 229 | (= str (do str 230 | (.replace /^\({1}/ "") 231 | (.replace /\){1}$/ ""))) 232 | str) 233 | str))) 234 | 235 | ; Removes extra pairs of parentheses around a string 236 | ; MUST NOT be applied to strings compiled from multiple expressions, only a SINGLE expression 237 | (= exports.dePairParenthesise (def dePairParenthesise str 238 | (if (isa str "string") 239 | (while (and (str.match /^\({2}/) 240 | (str.match /\){2}$/)) 241 | (= str (do str 242 | (.replace /^\({2}/ "(") 243 | (.replace /\){2}$/ ")"))) 244 | str) 245 | str))) 246 | 247 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; For Command Line ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 248 | 249 | ; Mostly copied from CoffeeScript source 250 | 251 | ; Merges objects, returning fresh copy with attributes from both sides 252 | (= exports.merge (def merge options overrides 253 | (extend (extend (:) options) overrides))) 254 | 255 | ; Extend source object with properties of another object (shallow copy) 256 | (= exports.extend (def extend object properties 257 | (do (over val key properties 258 | (= object[key] val)) 259 | object))) 260 | 261 | ; Return filename without extension 262 | (= exports.baseFileName (def baseFileName file (stripExt no) (useWinPathSep no) 263 | (do (= pathSep (if useWinPathSep /\\|\// /\//) 264 | parts (file.split pathSep) 265 | file (last parts)) 266 | (if (not (and stripExt (>= (file.indexOf ".") 0))) 267 | (return file)) 268 | (= parts (file.split ".")) 269 | (parts.pop) 270 | (if (and (is (last parts) "jisp") 271 | (> parts.length 1)) 272 | (parts.pop)) 273 | (parts.join ".")))) 274 | 275 | ; Repeat string `n` times 276 | (= exports.repeat (def repeat str n 277 | (do (= res "") 278 | (while (> n 0) 279 | (do (if (& n 1) (+= res str)) 280 | (>>>= n 1) 281 | (+= str str))) 282 | res))) 283 | 284 | (= exports.isJisp (def isJisp file 285 | (/\.jisp$/.test file))) 286 | --------------------------------------------------------------------------------