From cfec1f64e47b6b115d6448b8602499188235feb2 Mon Sep 17 00:00:00 2001 From: wes Date: Thu, 8 Jun 2017 19:24:48 -0400 Subject: [PATCH] messing around --- cexps.js | 135 - closures.js | 158 - cps.js | 5 - desugar.js | 141 - environments.js | 33 - errors.js | 38 - example.jl | 94 - fib.jl | 21 - free_vars.js | 159 - parse.js | 844 ----- pprint.js | 102 - prelude.jl | 118 - representation.js | 404 -- server/.app.js.swp | Bin 12288 -> 0 bytes server/.closures.js.swp | Bin 16384 -> 0 bytes server/.gitignore | 1 + server/.parse.js.swp | Bin 45056 -> 0 bytes server/.prelude.js.swp | Bin 12288 -> 0 bytes server/.representation.js.swp | Bin 20480 -> 0 bytes server/.test.js.swp | Bin 16384 -> 0 bytes server/.tokenize.js.swp | Bin 28672 -> 0 bytes server/.typecheck.js.swp | Bin 12288 -> 0 bytes server/.vm.js.swp | Bin 12288 -> 0 bytes server/assets/bundle.js | 6598 +-------------------------------- server/desugar.js | 4 +- server/package.json | 1 + server/prelude.js | 116 +- server/rollup.config.js | 4 +- server/routes/.index.js.swp | Bin 12288 -> 0 bytes server/tags/.jlambda.js.swp | Bin 12288 -> 0 bytes server/tags/.test.tag.swp | Bin 12288 -> 0 bytes server/tags/test.tag | 12 +- server/views/.index.pug.swp | Bin 12288 -> 0 bytes server/vm.js | 51 +- server/yarn.lock | 19 + test.js | 149 - tokenize.js | 432 --- tools.js | 104 - typecheck.js | 18 - vm.js | 66 - 40 files changed, 81 insertions(+), 9746 deletions(-) delete mode 100644 cexps.js delete mode 100644 closures.js delete mode 100644 cps.js delete mode 100644 desugar.js delete mode 100644 environments.js delete mode 100644 errors.js delete mode 100644 example.jl delete mode 100644 fib.jl delete mode 100644 free_vars.js delete mode 100755 parse.js delete mode 100644 pprint.js delete mode 100644 prelude.jl delete mode 100644 representation.js delete mode 100644 server/.app.js.swp delete mode 100644 server/.closures.js.swp create mode 100644 server/.gitignore delete mode 100644 server/.parse.js.swp delete mode 100644 server/.prelude.js.swp delete mode 100644 server/.representation.js.swp delete mode 100644 server/.test.js.swp delete mode 100644 server/.tokenize.js.swp delete mode 100644 server/.typecheck.js.swp delete mode 100644 server/.vm.js.swp delete mode 100644 server/routes/.index.js.swp delete mode 100644 server/tags/.jlambda.js.swp delete mode 100644 server/tags/.test.tag.swp delete mode 100644 server/views/.index.pug.swp delete mode 100755 test.js delete mode 100755 tokenize.js delete mode 100644 tools.js delete mode 100644 typecheck.js delete mode 100755 vm.js diff --git a/cexps.js b/cexps.js deleted file mode 100644 index f996a65..0000000 --- a/cexps.js +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Defines the data structures associated with Continuation Expressions (cexps) - * The object here is to have an intermediate representation that allows a code generator backend - * to easily create sequential code. In other words we are taking an alegraic/applicative language - * and translating it to something more similar to the "one word at a time" architecture of the von-Neumann - * architecture - */ - -var cexp = { - type : "cexp" -}; - -function record(values_accesspaths, - w, - next_cexp) { - this.values_accesspaths = values_accesspaths; - this.w = w; - this.next_cexp = next_cexp; - return this; -} - -record.prototype = cexp; - -function select(i, v, w, next_cexp) { - this.i = i; - this.v = v; - this.w = w; - this.next_cexp = next_cexp; - return this; -} -select.prototype = cexp; - -function offset(i, v, w, next_cexp) { - this.i = i; - this.v = v; - this.w = w; - this.next_cexp = next_cexp; - return this; -} -offset.prototype = cexp; - -function app(k, vs) { - this.k = k; - this.vs = vs; - return this; -} -app.prototype = cexp; - -function fix(fs, next_cexp) { - this.fs = fs; - this.next_cexp = next_cexp; - return this; -} -fix.prototype = cexp; - -function switchl(v, cexps) { - this.v = v; - this.cexps = cexps; - return this; -} -switchl.prototype = cexp; - -function primop(op, vals, vars, next_cexp) { - this.op = op; - this.vals = vals; - this.vars = vars; - this.next_cexp = next_cexp; - return this; -} -primop.prototype = cexp; - -function accessPath(offp, selp) { - this.offp = offp; - this.selp = selp; - return this; -} - -var primoptype = { - type : "primop", - equal : function(pOp) { - return this.name === pOp.name; - } -}; - -function Primop(name) { - function ptype() { - this.name = name; - return this; - } - ptype.prototype = primoptype; - return new ptype(); -} - -var times = Primop("+"); -var plus = Primop("+"); -var div = Primop("div"); -var tilde = Primop("~"); -var ieql = Primop("ieql"); -var ineq = Primop("ineq"); -var lessthan = Primop("<"); -var lessoreq = Primop("<="); -var greatthan = Primop(">"); -var greatoreq = Primop(">="); -var bang = Primop("!"); -var subscript = Primop("subscript"); -var ordof = Primop("ordof"); -var assign = Primop(":="); -var unboxedassign = Primop("unboxedassign"); -var update = Primop("update"); -var unboxedupdate = Primop("unboxedupdate"); -var store = Primop("store"); -var makeref = Primop("makeref"); -var makerefunboxed = Primop("makerefunboxed"); -var alength = Primop("alength"); -var slength = Primop("slength"); -var gethdlr = Primop("gethdlr"); -var sethdlr = Primop("sethdlr"); -var boxed = Primop("boxed"); -var fadd = Primop("fadd"); -var fsub = Primop("fsub"); -var fdiv = Primop("fdiv"); -var fmul = Primop("fmul"); -var feql = Primop("feql"); -var fneq = Primop("fneq"); -var fge = Primop("fge"); -var fgt = Primop("fgt"); -var fle = Primop("fle"); -var flt = Primop("flt"); -var rshift = Primop("rshift"); -var lshift = Primop("lshift"); -var orb = Primop("orb"); -var andb = Primop("andb"); -var xorb = Primop("xorb"); -var notb = Primop("notb"); - diff --git a/closures.js b/closures.js deleted file mode 100644 index c261113..0000000 --- a/closures.js +++ /dev/null @@ -1,158 +0,0 @@ -/* Takes an AST and converts all of the functions into "closures" - * A closure is a triple of: - * the bound variables in a function or let - * the free variables in a function or let - * a function body or let body and bound values (if it is an escaping closure only) - * The closure has the property that all of the free variables of the function or let - * are in the environment, or an exception is raised because the variable is not bound - * in the current environment. - * A free variable is simply those that are not in the list of formal parameters or bound variables if it is a let - * - * Therefore in order to call a closure one must first extract the actual function and then - * call the function with the environment associated with it. - * For the purposes of type checking it does not matter how the function gets called, the environment - * is only used for looking up the types of names. Formal parameters are given type variables. - * - * The first phase of closure conversion is not really closure conversion exactly. - * All it does is find out the free variables in scope and tie those up into a data structure with their types later. - * The second phase will be done to the CPS language and closures will actually lambda-lifted out potentially. - */ - -var rep = require("./representation.js"); -var errors = require("./errors.js"); -var parser = require("./parse.js"); -var $ = require("./tools.js"); -var _ = require("underscore"); - -var notEmpty = _.compose($.not, _.partial(_.equal, [])); - -function fvs(stx) { - switch (stx.exprType) { - case "Integer": - return []; - case "Float": - return []; - case "String": - return []; - case "Function": - return []; - case "Nil": - return []; - case "Bool": - return []; - case "Let": - return []; - case "Unary": - return _.flatten([stx.op.ident, fvs(stx.val)]); - case "Definition": - return _.flatten(fvs(stx.val)); - case "Application": - var vs = _.flatten(fvs(stx.p)); - var f_fvs = _.flatten(fvs(stx.func)); - return _.flatten([vs, f_fvs]); - case "If": - if (stx.elseexp) { - var cond_fvs = fvs(stx.condition); - var then_fvs = fvs(stx.thenexp); - var else_fvs = fvs(stx.elseexp); - return _.flatten([cond_fvs, then_fvs, else_fvs]); - } - else { - return _.flatten([fvs(stx.condition), fvs(stx.thenexp)]); - } - break; - case "Name": - return [stx.ident]; - } -} - -function annotate_fvs(stx) { - /* Takes a stx object that is either - * a lambda - * a let - * and returns a closure wrapped around that stx object - */ - if (stx.exprType !== "Function" && - stx.exprType !== "Let") { - throw errors.JInternalError( - ["Tried to calculate the free variables of", - "something that was not a function or let.\n", - "That something was a: " + stx.exprType +"\n"].reduce( - function (a,b) { - return a+" "+b; - }, "")); - } - var variables, free_variables, bound_vars, stx_type; - - switch (stx.exprType) { - case "Let": - bound_vars = stx.pairs.map( - function (stx) { - return stx.ident.ident; - }); - var let_fvs = stx.pairs.map(fvs); - var body_fvs = fvs(stx.body); - variables = _.flatten(let_fvs); - $.extend(variables, _.flatten(body_fvs)); - break; - case "Function": - bound_vars = [stx.p.ident,]; - variables = fvs(stx.body); - break; - } - free_variables = _.difference(_.uniq(variables), bound_vars); - return new rep.Closure(bound_vars, free_variables, stx, []); -} - -/* - * This traverse the tree and gathers up all of the free variables of various functions/let bindings - */ -function annotate_fvs_all(stx) { - var closure; - switch (stx.exprType) { - case "Let": - closure = annotate_fvs(stx); - closure.body.pairs = closure.body.pairs.map(annotate_fvs_all); - closure.body = annotate_fvs_all(closure.body.body); - return closure; - case "Function": - closure = annotate_fvs(stx); - closure.body.body = annotate_fvs_all(closure.body.body); - return closure; - case "Unary": - stx.val = annotate_fvs_all(stx.val); - return stx; - case "Application": - stx.func = annotate_fvs_all(stx.func); - stx.p = annotate_fvs_all(stx.p); - return stx; - case "If": - if (stx.elseexp) { - stx.condition = annotate_fvs_all(stx.condition); - stx.thenexp = annotate_fvs_all(stx.thenexp); - stx.elseexp = annotate_fvs_all(stx.elseexp); - return stx; - } - else { - stx.condition = annotate_fvs_all(stx.condition); - stx.thenexp = annotate_fvs_all(stx.thenexp); - return stx; - } - break; - case "Definition": - stx.val = annotate_fvs_all(stx.val); - return stx; - default: - return stx; - } -} - - -function test(src) { - var ast = parser.parse(src); -} - -//console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing")); -module.exports = { - annotate_fvs : annotate_fvs_all -}; diff --git a/cps.js b/cps.js deleted file mode 100644 index afb69f5..0000000 --- a/cps.js +++ /dev/null @@ -1,5 +0,0 @@ -#! /usr/bin/node - -var typ = require("representation.js"); - - diff --git a/desugar.js b/desugar.js deleted file mode 100644 index a404fef..0000000 --- a/desugar.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This module takes a parse tree in a surface format - * and transforms it into the "core" language which is - * much simpler and easier to type-check, optimize, and evaluate - */ - -var typ = require("./representation.js"); -var errors = require("./errors.js"); -var _ = require("underscore"); - -// Lists get desugared to nested function calls -// i.e. (cons (cons (cons ...))) -function desugarList(lst) { - if (lst.xs.length <= 0) { - return new typ.Nil(); - } - else { - var x = desugar(lst.xs[0]); - var rest = lst.xs.slice(1); - return new typ.App(new typ.App(new typ.Name("(:)"), x), desugarList(new typ.ListT(rest))); - } -} - -function desugarDefFunc(def) { - return new typ.Def(def.ident, - curryFunc(def.params, - def.body)); -} - -function curryFunc(ps, body) { - var result; - if (_.isEmpty(ps)) { - return desugar(body); - } - else { - result = new typ.FuncT(desugar(_.first(ps)), - curryFunc(_.rest(ps), body)); - result.charnum = ps.charnum; - result.linenum = ps.linenum; - return result; - } -} - - -function desugarLet(stx) { - var values = stx.pairs.map(desugar); - return new typ.LetExp(values, desugar(stx.body)); -} - -function sugarTypeDecl(stx) { - var type; - var expression; - type = stx.p; - expression = desugar(stx.func.p); - expression.linenum = stx.linenum; - expression.charnum = stx.charnum; - return new typ.TypeDecl(expression, type); -} - -function desugarDefType(stx, typeEnv) { - var result; - var rhs = desugar(stx.rhs); - var name = stx.lhs.name; - typeEnv[name] = rhs; - - result = new typ.DefType(stx.lhs, desugar(stx.rhs)); - result.linenum = stx.linenum; - result.charnum = stx.charnum; - return result; -} - - -function desugar(stx, typeEnv) { - var typeExpTest; - - switch (stx.exprType) { - case "If": - if (stx.elseexp) { - return new typ.If(desugar(stx.condition, typeEnv), desugar(stx.thenexp, typeEnv), desugar(stx.elseexp, typeEnv)); - } - return new typ.If(desugar(stx.condition, typeEnv), desugar(stx.thenexp, typeEnv)); - case "FunctionDefinition": - return desugarDefFunc(stx); - case "Definition": - return new typ.Def(stx.ident, desugar(stx.val, typeEnv)); - case "TypeDefinition": - return desugarDefType(stx, typeEnv); - case "Name": - return stx; - case "Application": - if ((stx.func.func !== undefined ) && - (stx.func.func.ident === "::")) { - /* It's a type declaration probably (will be verified later) - * In this case we actually *add* syntax here to differentiate type declarations - * from normal function application - */ - typeExpTest = typ.isTypeExpr(stx.p); - - if (typeExpTest.failed !== undefined && - typeExpTest.failed) { - throw errors.JInternalError( - "Type declaration error near line " + stx.linenum + " at character #"+stx.charnum + - "\n"+typeExpTest.stx.exprType+" (" + typeExpTest.stx.val + ") found where a type operator or type application was expected"); - } - return sugarTypeDecl(stx); - } - - if ((stx.func.ident === "-" || - stx.func.ident === "+") && - stx.p) { - return new typ.UnaryOp(desugar(stx.func, typeEnv), desugar(stx.p, typeEnv)); - } - if (stx.p) { - return new typ.App(desugar(stx.func, typeEnv), desugar(stx.p, typeEnv)); - } - return new typ.App(stx.func); - case "Function": - return curryFunc(stx.p, stx.body); - case "List": - return desugarList(stx); - case "Bool": - return stx; - case "String": - return stx; - case "Float": - return stx; - case "Integer": - return stx; - case "Let": - return desugarLet(stx); - default: - return stx; - } -} - -module.exports = { desugar : desugar }; -//var test = typ.ListT([1,2,3]); - -//console.log(desugarList(test)); - - diff --git a/environments.js b/environments.js deleted file mode 100644 index 9331aaa..0000000 --- a/environments.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * An environment is just an object that maps identifiers to JLambda expressions - * with a few built-in (a standard Prelude environment) - */ - -var errors = require("./errors.js"); -var rep = require("./representation.js"); - -// creates a new environment initialized with the pairs in values -function makeEnv(name, values) { - var env = {}; - env.name = name; - env.bindings = {}; - for (var i = 0; i < values.length; i++) { - name = values[i][0]; - var val = values[i][1]; - env.bindings[name] = val; - } - return env; -} - -function lookup(name, env) { - var value = env.bindings[name]; - if (!value) { - throw errors.JUnboundError(name, env.name); - } - return value; -} - -module.exports = { - lookup : lookup, - makeEnv : makeEnv -}; diff --git a/errors.js b/errors.js deleted file mode 100644 index 7456886..0000000 --- a/errors.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file defines common error objects - * for reporting on syntax errors, type errors, - * and perhaps runtime exceptions although I have - * not thought about how that will work much - */ - -function JSyntaxError(linenum, charnum, message) { - this.linenum = linenum; - this.charnum = charnum; - this.errormessage = message; - this.stxerror = function() { - console.log("Syntax Error\n", - "Line #", this.linenum,"\n", - "Near character #", this.charnum, "\n", - this.errormessage); - }; - return this; -} - -function JTypeError(linenum, charnum, token, message) { - this.linenum = linenum; - this.charnum = charnum; - this.errormessage = message; - this.token = token; - return this; -} - -function JInternalError(message) { - this.errormessage = message; - return this; -} - -module.exports = - {JSyntaxError : JSyntaxError, - JTypeError : JTypeError, - JInternalError : JInternalError - }; diff --git a/example.jl b/example.jl deleted file mode 100644 index 4599e01..0000000 --- a/example.jl +++ /dev/null @@ -1,94 +0,0 @@ -def foo# 3 - -deftype Foo (A -> B) - -;; here is a comment -; here is another comment - -deftype (Foo a b) - (a -> b) - -(qat :: A -> b) -def tdeftype (lambda a b c -> (a + b)) - -def (add a b) - (a + b) - -def wat [[1,2,3], [4,5,6]] - -def (catstrs strs) - (foldr f - (head strs) - (tail strs)) - -def strs ["aa", "bb"] - -def (mymap f xs) - if ((length xs) == 0) - then -xs - else - ((f (head xs)) - : (mymap f (tail xs))) - -def empty [] - -def getFile - (readFile "./parse.js") - -;;def fileLines -;; (getFile >>= -;; ((mapM_ putStrLn) . lines)) - -def (testUnary n) - ((-n) + n) - -def (foo bar) - let { - lol = [1, - (lambda qwerty blah -> - [qerty, blah, - (lambda whatever -> whatever)])] - } - if bar - then [lol,(- 1.2),"lulz",lol] - else if something - then [,] - else - somethingelse - -def (splitHelp acc xs ys) - if (null xs) - then ((reverse acc), ys) - else if (null (tail xs)) - then ((reverse acc), ys) - else - (splitHelp ((head ys) : acc) - (tail (tail xs)) - (tail ys)) - -def (splitxs xs) - (splitHelp [] xs xs) - -def r def - { - a = 4 - } - a - -def main - let { - (f a) -> a - unary = (print (testUnary 6)) - splitted = def { - xs = (fst (splitxs [12,3,4,56])) - } (xs ++ [0,9]) - } - if False - then superduper - else - (unary + - fileLines + - (print splitted)) - -def blah (3 / 4) diff --git a/fib.jl b/fib.jl deleted file mode 100644 index 2434e4a..0000000 --- a/fib.jl +++ /dev/null @@ -1,21 +0,0 @@ -def (fib n) - if (n == 0) - then 0 - else if (n == 1) - then 1 - else - ((fib (n-1)) + - (fib (n-2))) - -def (fact n) - if (n == 0) - then 1 - else - ((fact (n-1)) * n) - -def ns [1,2,3,4,5] - -def main - ((print (fib 19)) >> - (print (ns >>= (return . fact)))) - diff --git a/free_vars.js b/free_vars.js deleted file mode 100644 index caf3198..0000000 --- a/free_vars.js +++ /dev/null @@ -1,159 +0,0 @@ -/* Takes an AST and converts all of the functions into "closures" - * A closure is a triple of: - * the bound variables in a function or let - * the free variables in a function or let - * a function body or let body and bound values (if it is an escaping closure only) - * The closure has the property that all of the free variables of the function or let - * are in the environment, or an exception is raised because the variable is not bound - * in the current environment. - * A free variable is simply those that are not in the list of formal parameters or bound variables if it is a let - * - * Therefore in order to call a closure one must first extract the actual function and then - * call the function with the environment associated with it. - * For the purposes of type checking it does not matter how the function gets called, the environment - * is only used for looking up the types of names. Formal parameters are given type variables. - * - * The first phase of closure conversion is not really closure conversion exactly. - * All it does is find out the free variables in scope and tie those up into a data structure with their types later. - * The second phase will be done to the CPS language and closures will actually lambda-lifted out potentially. - */ - -var rep = require("./representation.js"); -var errors = require("./errors.js"); -var parser = require("./parse.js"); -var $ = require("./tools.js"); -var _ = require("underscore"); - -var notEmpty = _.compose($.not, _.partial(_.equal, [])); - -function fvs(stx) { - switch (stx.exprType) { - case "Integer": - return []; - case "Float": - return []; - case "String": - return []; - case "Function": - return []; - case "Nil": - return []; - case "Bool": - return []; - case "Let": - return []; - case "Unary": - return _.flatten([stx.op.ident, fvs(stx.val)]); - case "Definition": - return _.flatten(fvs(stx.val)); - case "Application": - var vs = _.flatten(fvs(stx.p)); - var f_fvs = _.flatten(fvs(stx.func)); - return _.flatten([vs, f_fvs]); - case "If": - if (stx.elseexp) { - var cond_fvs = fvs(stx.condition); - var then_fvs = fvs(stx.thenexp); - var else_fvs = fvs(stx.elseexp); - return _.flatten([cond_fvs, then_fvs, else_fvs]); - } - else { - return _.flatten([fvs(stx.condition), fvs(stx.thenexp)]); - } - break; - case "Name": - return [stx.ident]; - } -} - -function annotate_fvs(stx) { - /* Takes a stx object that is either - * a lambda - * a let - * and returns a closure wrapped around that stx object - */ - if (stx.exprType !== "Function" && - stx.exprType !== "Let") { - throw errors.JInternalError( - ["Tried to calculate the free variables of", - "something that was not a function or let.\n", - "That something was a: " + stx.exprType +"\n"].reduce( - function (a,b) { - return a+" "+b; - }, "")); - } - var variables, free_variables, bound_vars, stx_type; - - switch (stx.exprType) { - case "Let": - bound_vars = stx.pairs.map( - function (stx) { - return stx.ident.ident; - }); - var let_fvs = stx.pairs.map(fvs); - var body_fvs = fvs(stx.body); - variables = _.flatten(let_fvs); - $.extend(variables, _.flatten(body_fvs)); - break; - case "Function": - bound_vars = [stx.p.ident,]; - variables = fvs(stx.body); - break; - } - free_variables = _.difference(_.uniq(variables), bound_vars); - return new rep.Closure(bound_vars, free_variables, stx, []); -} - -/* - * This traverse the tree and gathers up all of the free variables of various functions/let bindings - */ -function annotate_fvs_all(stx) { - var closure; - switch (stx.exprType) { - case "Let": - closure = annotate_fvs(stx); - closure.body.pairs = closure.body.pairs.map(annotate_fvs_all); - closure.body = annotate_fvs_all(closure.body.body); - return closure; - case "Function": - closure = annotate_fvs(stx); - closure.body.body = annotate_fvs_all(closure.body.body); - return closure; - case "Unary": - stx.val = annotate_fvs_all(stx.val); - return stx; - case "Application": - stx.func = annotate_fvs_all(stx.func); - stx.p = annotate_fvs_all(stx.p); - return stx; - case "If": - if (stx.elseexp) { - stx.condition = annotate_fvs_all(stx.condition); - stx.thenexp = annotate_fvs_all(stx.thenexp); - stx.elseexp = annotate_fvs_all(stx.elseexp); - return stx; - } - else { - stx.condition = annotate_fvs_all(stx.condition); - stx.thenexp = annotate_fvs_all(stx.thenexp); - return stx; - } - break; - case "Definition": - stx.val = annotate_fvs_all(stx.val); - return stx; - default: - return stx; - } -} - - -function test(src) { - var ast = parser.parse(src); -} - -//console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing")); -module.export = { - test : test, - annotate_fvs: annotate_fvs_all -}; diff --git a/parse.js b/parse.js deleted file mode 100755 index b389060..0000000 --- a/parse.js +++ /dev/null @@ -1,844 +0,0 @@ -#! /usr/bin/node -var fs = require("fs"); -var typ = require("./representation.js"); -var $ = require("./tools.js"); -var _ = require("underscore"); -var tokenizer = require("./tokenize.js"); -var desugarer = require("./desugar.js"); -var pprint = require("./pprint.js"); -var error = require("./errors.js"); -var closure = require("./closures.js"); -var print = console.log; - -function sourcePos(tokens, linenum, charnum) { - if (!tokens || tokens.length === 0) { - return { linenum : linenum, - charnum : charnum - }; - } - return { - linenum : fst(tokens)[3], - charnum : fst(tokens)[2] - }; -} - -function addSrcPos(stx, tokens, linenum, charnum) { - var pos = sourcePos(tokens, linenum, charnum); - stx.linenum = pos.linenum; - stx.charnum = pos.charnum; - return stx; -} - -/* Gets the first token from the right side of the stack */ -function fst(ts) { - return ts[ts.length-1]; -} - -/* Gets the second token from the right side of the stack */ -function snd(ts) { - return ts[ts.length-2]; -} - -/*Checks if the next token is not followed by any of ``checks'' */ -function notFollowedBy(tokens, checks, linenum, charnum) { - if (!fst(tokens)) { - throw error.JSyntaxError(0,0,"unexpected end of source"); - } - var nextT = fst(tokens)[0]; - if (checks.some(function (x) { - return x === nextT; - })) - return false; - else - return true; -} - -/* returns a function that takes a parameter and - checks if it is in the array ``props''*/ -function makeChecker(props) { - return function(x) { - return x && props.some(function (y) {return y(x);}); - }; -} - -function tokTypeCheck(name) { - return function(tok) { - return tok[0] === name; - }; -} - -function formTypeCheck(stxtype) { - return function(stx) { - return stx.exprType === stxtype; - }; -} - -/*Tries to parse until the prediction ``valid'' fails or the wrong type is parsed - Collects the results into an array and returns it*/ -function parseMany(parse, exprType, valid, tokens, charnum, linenum) { - if (!fst(tokens)) { - throw error.JSyntaxError(charnum, - linenum, - "Unexpected end of source"); - } - var current = fst(tokens)[0]; - var results = []; - var parsed; - - if (valid(fst(tokens))) { - parsed = parse(tokens); - } - else { - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Unexpected token: ``"+fst(tokens)[0]+"''"); - } - results.push(parsed); - - //make sure there are at least 2 tokens to parse - if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) { - while (valid(snd(tokens))) { - if (!(valid(fst(tokens)))) { - break; - } - results.push(parse(tokens)); - if (!exprType(fst(results).exprType)) { - break; - } - if (fst(tokens)) { - current = fst(tokens)[0]; - } - else { - throw error.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - if (tokens.length <= 1) { - break; - } - } - } - //do the same validity check as before and in the loop - if (!fst(tokens)) { - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "unexpected end of source"); - } - if (valid(fst(tokens))) { - results.push(parse(tokens)); - } - return results; -} - - -/* Tries to parse exprType separated by the token between - * e.g. ,,... - */ -function parseBetween(exprType, between, tokens, charnum, linenum) { - var first = parse(tokens); - var items; - var parsed; - - if (!exprType(first)) { - throw error.JSyntaxError(fst(tokens)[2], fst(tokens)[3], "Unexpected token: ``"+fst(tokens)[0]+"''"); - } - - items = [first]; - - if (tokens.length > 1 && fst(tokens)[0] === between) { - while (fst(tokens)[0] === between) { - tokens.pop(); - parsed = parse(tokens); - if (!fst(tokens)) - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Missing terminator: "+between); - items.push(parsed); - } - return items; - } - return items; -} - -function parseList(tokens, linenum, charnum) { - var xs; - var result; - - if (fst(tokens)[0] === "right_square") { - xs = []; - } - else if (fst(tokens)[0] === "comma") { - tokens.pop(); - xs = []; - } - else { - xs = parseBetween(function (x) { - return true; - }, "comma", tokens, fst(tokens)[3], fst(tokens)[2]); - } - if (!fst(tokens) || fst(tokens)[0] !== "right_square") { - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "list must be terminated by ]"); - } - tokens.pop(); - result = addSrcPos(new typ.ListT(xs), tokens, linenum, charnum); - return result; -} - - -function parseDefFunction(tokens, linenum, charnum) { - var fname = parse(tokens); - var parameters; - var result; - var body; - - if (fname.exprType !== "Name") { - throw error.JSyntaxError(linenum, - charnum, - "Expected an identifier in function definition"); - } - if (fst(tokens)[0] === "right_paren") { - parameters = []; - } - else { - parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - } - if (!tokens || (fst(tokens)[0]) !== "right_paren") { - throw error.JSyntaxError(linenum, - charnum, - "Formal parameters must be followed by )"); - } - tokens.pop(); - body = parse(tokens); - result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum); - return result; -} - -validLet = makeChecker(["Definition", "FunctionDefinition"].map(formTypeCheck)); -letEnd = _.compose($.not, makeChecker(["right_brace"].map(tokTypeCheck))); - -function parseLetForm(tokens, linenum, charnum) { - var result; - var pairs; - var body; - - if (!fst(tokens)) { - error.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - pairs = parseMany(parseLetItem, - validLet, - letEnd, - tokens, - charnum, - linenum); - if (fst(tokens) && fst(tokens)[0] !== "right_brace") { - throw error.JSyntaxError(fst(tokens)[2], - fst(tokens)[3], - "let/def form must have a closing }"); - } - if (!fst(tokens)) { - throw error.JSyntaxError(_.last(pairs).linenum, - _.last(pairs).charnum, - "Unexpected end of source"); - } - tokens.pop(); - if (tokens.length <= 0) { - throw error.JSyntaxError(_.last(pairs).linenum, - _.last(pairs).charnum, - "let/def form must have a body"); - } - body = parse(tokens); - if (body.exprType === "Definition" || - body.exprType === "FunctionDefinition") { - throw error.JSyntaxError(body.linenum, - body.charnum, - "Body of a let/def expression cannot be a definition"); - } - result = addSrcPos(new typ.LetExp(pairs, body), tokens, body.linenum, body.charnum); - return result; - -} - -function parseLetFunction(tokens, linenum, charnum) { - var fname = parse(tokens); - var parameters; - var result; - var body; - - if (fname.exprType != "Name") { - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Expected an identifier in function definition"); - } - if (fst(tokens)[0] === "right_paren") { - parameters = []; - } - else { - parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - } - if ((fst(tokens)[0]) !== "right_paren") { - throw error.JSyntaxError(linenum, - charnum, - "Formal parameters must be followed by )"); - } - tokens.pop(); - if (fst(tokens)[1] !== "->") { - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Function parameters in let/def form must be followed by ->"); - } - tokens.pop(); - body = parse(tokens); - result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum); - return result; -} - -function parseLetBinding(tokens, linenum, charnum) { - var name = parse(tokens); - var result; - var bound; - - if (name.exprType != "Name") { - throw error.JSyntaxError(name.linenum, - name.charnum, - "Expected an identifier in let/def binding"); - } - if (!fst(tokens) || fst(tokens)[1] !== "=") { - throw error.JSyntaxError(name.linenum, - name.charnum, - "An identifier in a let/def binding must be followed by ``=''"); - } - tokens.pop(); - if (!notFollowedBy(tokens, - ["comma", "arrow", "right_brace", "right_square"], - name.linenum, - name.charnum)) { - throw error.JSyntaxError(name.linenum, - name.charnum, - "The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]); - } - bound = parse(tokens); - if (bound.exprType === "Definition" || - bound.exprType === "FunctionDefinition") { - throw error.JSyntaxError(bound.linenum, - bound.charnum, - "A definition cannot be the value of a binding"); - } - result = addSrcPos(new typ.Def(name, bound), tokens, bound.linenum, bound.charnum); - return result; -} - -function parseLetItem(tokens) { - var linenum = fst(tokens)[3]; - var charnum = fst(tokens)[2]; - - if (fst(tokens) && fst(tokens)[0] === "left_paren") { - tokens.pop(); - return parseLetFunction(tokens, - linenum, - charnum); - } - else { - return parseLetBinding(tokens, - linenum, - charnum); - } -} - -function parseDataType(tokens, linenum, charnum) { - var typeName = parse(tokens, linenum, charnum); - var typeParams; - var typeBody; - var result; - - if (typeName.exprType !== "TypeOperator") { - throw error.JSyntaxError(typeName.linenum, - typeName.charnum, - "Expected a type operator in data type definition"); - } - if (fst(tokens)[0] !== "right_paren") { - parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - } - else { - parameters = []; - } - if (!tokens || (fst(tokens)[0]) !== "right_paren") { - throw error.JSyntaxError(_.last(parameters).linenum, - _.last(parameters).charnum, - "Data type parameters must be followed by )"); - } - tokens.pop(); - typeBody = parse(tokens); - result = addSrcPos(new typ.DataType(typeName, parameters, typeBody), tokens, typeBody.linenum, typeBody.charnum); - - return result; -} - - - -function parseDefType(tokens, linenum, charnum) { - var result; - var rhs; - var lhs; - - if (tokens.length < 2) { - /* Minimal number of tokens required is 2 - * because it could be 'deftype Foo Blah' - */ - throw error.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - if (fst(tokens)[0] === "left_paren") { - /* It's an actual data type definition - * i.e. not just an alias - */ - tokens.pop(); - return parseDataType(tokens, linenum, charnum); - } - - if (notFollowedBy(tokens, ["constructor"], linenum, charnum)) { - throw error.JSyntaxError(linenum, - charnum, - "deftype must be followed by a single constructor" + - " if it is not a data type definition with type variables"); - } - else { - lhs = parse(tokens, linenum, charnum); - if (!tokens) { - throw error.JSyntaxError(lhs.linenum, - lhs.charnum, - "Unexpected end of source"); - } - if (lhs.exprType !== "TypeOperator") { - throw error.JSyntaxError(lhs.linenum, - lhs.charnum, - "left-hand side of type alias was not a type operator"); - } - rhs = parse(tokens, linenum, charnum); - - if (rhs.exprType !== "Application" && - rhs.exprType !== "TypeOperator") { - throw error.JSyntaxError(rhs.linenum, - rhs.charnum, - "was expecting an application or type operator on the right-hand side of a type alias"); - } - result = addSrcPos(new typ.DefType(lhs, rhs), tokens, rhs.linenum, rhs.charnum); - return result; - } -} - - - - - -function parseDef(tokens, linenum, charnum) { - var result; - var identifier; - var bound; - - if (tokens.length < 2) { - /* Minimal number of tokens required is 2 - * because it could be 'def foo blah' - */ - throw error.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - if (fst(tokens)[0] === "left_paren") { - /* It's a function definition */ - tokens.pop(); - return parseDefFunction(tokens, linenum, charnum); - } - - if (fst(tokens)[0] === "left_brace") { - /* It's a let/def form */ - tokens.pop(); - return parseLetForm(tokens, - fst(tokens)[3], - fst(tokens)[2]); - } - - if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) { - throw error.JSyntaxError(linenum, - charnum, - "def must be followed by identifier, not "+fst(tokens)[0]); - } - else { - identifier = parse(tokens); - if (!fst(tokens)) - throw error.JSyntaxError(identifier.linenum, - identifier.charnum, - "Unexpected end of source"); - if (!notFollowedBy(tokens, - ["comma", "arrow", "right_brace", "right_square"], - identifier.linenum, - identifier.charnum)) { - throw error.JSyntaxError(identifier.linenum, - identifier.charnum, - "def " + identifier.val + " must not be followed by " + fst(tokens)[0]); - } - bound = parse(tokens); - if (bound.exprType === "Definition" || - bound.exprType === "FunctionDefinition") { - throw error.JSyntaxError(bound.linenum, - bound.charnum, - "A definition cannot be the value of a binding"); - } - result = addSrcPos(new typ.Def(identifier, bound), tokens, bound.linenum, bound.charnum); - return result; - } - } - -function parseDefOp(tokens, linenum, charnum) { - var result; - var names; - var pattern; - - if (fst(tokens)[0] !== "integer" || - fst(tokens)[1] < 1) { - throw error.JSyntaxError(linenum, - charnum, - "defop must be followed by integer precedence >= 1"); - } - tokens.pop(); - - if (fst(tokens)[1] !== "Left" && fst(tokens)[1] !== "Right") { - throw error.JSyntaxError(linenum, - charnum, - "defop must be followed by precedence and then either Left or Right"); - } - tokens.pop(); - if (fst(tokens)[0] !== "left_paren") { - throw error.JSyntaxError(linenum, - charnum, - "defop arguments must start with ("); - } - tokens.pop(); - if (!(tokens.slice(tokens.length-3, - tokens.length).every(function(x) { - return x[0] === "identifier"; - }))) { - throw error.JSyntaxError(linenum, - charnum, - "defop must be surrounded by exactly 3 identifiers"); - } - pattern = tokens.slice(tokens.length-3, - tokens.length); - tokens.pop(); tokens.pop(); tokens.pop(); - if (fst(tokens)[0] !== "right_paren") { - throw error.JSyntaxError(linenum, - charnum, - "defop pattern must be terminated with )"); - } - tokens.pop(); - names = [new typ.Name(pattern[1][1]), - new typ.Name(pattern[0][1]), - new typ.Name(pattern[2][1])]; - names.map(function(name) { - name.linenum = linenum; - name.charnum = charnum; - return name; - }); - - result = addSrcPos(new typ.DefFunc(names[0], - names.slice(1,3), - parse(tokens)), - tokens, - _.last(names).linenum, - _.last(names).charnum); - return result; -} - - - -function parseIf(tokens, linenum, charnum) { - var result; - var ifC; - var thenC; - var elseC; - - if (!notFollowedBy(tokens, - ["def","comma","lambda"], - linenum, - charnum)) { - throw error.JSyntaxError(linenum, - charnum, - "``if'' cannot be followed by "+fst(tokens)[0]) ; - } - else { - ifC = parse(tokens); - if (!fst(tokens) || fst(tokens)[0] !== "thenexp") { - throw error.JSyntaxError(ifC.linenum, - ifC.charnum, - "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]); - } - else { - tokens.pop(); - thenC = parse(tokens); - - if (fst(tokens) && fst(tokens)[0] === "elsexp") { - tokens.pop(); - if (_.size(tokens) < 1) { - throw error.JSyntaxError(thenC.linenum, - thenC.charnum, - "Unexpected end of source"); - } - else { - elseC = parse(tokens); - result = addSrcPos(new typ.If(ifC, thenC, elseC), tokens, elseC.linenum, elseC.charnum); - return result; - } - } - else { - throw error.JSyntaxError(thenC.linenum, - thenC.charnum, - "If expression must include an else variant"); - } - } - } -} - -var validName = makeChecker(["Name"].map(formTypeCheck)); - -function validFormPar(tok) { - return tok[0] === "identifier" && - tok[1] !== "->"; -} - -function parseLambda(tokens, linenum, charnum) { - var result; - var parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - if (fst(tokens)[1] !== "->") { - throw error.JSyntaxError(_.last(parameters).linenum, - _.last(parameters).charnum, - "arrow must follow parameters in lambda, not "+fst(tokens)[0]); - } - tokens.pop(); - var body = parse(tokens); - result = addSrcPos(new typ.FuncT(parameters, body), tokens, body.linenum, body.charnum); - return result; -} - -var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"].map(tokTypeCheck); -var validArgument = _.compose($.not, makeChecker(invalidArguments)); -var validArgTypes = _.compose($.not, makeChecker(["Definition"].map(formTypeCheck))); - -/* Parses function application (either infix or prefix) */ -function computeApp(tokens, charnum, linenum) { - var lhs = parse(tokens); - var next; - var result; - var parameters; - - if (fst(tokens)) { - next = fst(tokens); - } - else { - throw error.JSyntaxError(lhs.linenum, - lhs.charnum, - "Unexpected end of source"); - } - if (typ.OPInfo[next[1]]) { - /* it's an infix expression */ - result = parseInfix(tokens, 1, lhs, lhs.linenum, lhs.charnum); - if (!fst(tokens) || fst(tokens)[0] !== "right_paren") { - throw error.JSyntaxError(lhs.linenum, - lhs.charnum, - "Mismatched parentheses or missing parenthesis on right-hand side"); - } - else { - tokens.pop(); - return result; - } - } - else { - /* it's a prefix application */ - if (fst(tokens)[0] !== "right_paren") { - parameters = parseMany(parse, - validArgTypes, - validArgument, - tokens, - fst(tokens)[2], - fst(tokens)[3]); - } - else { - parameters = []; - } - if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") { - throw error.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Mismatched parentheses or missing parenthesis on right-hand side"); - } - else { - tokens.pop(); - return addSrcPos(typ.makeApp(lhs, parameters), tokens, linenum, charnum); - } - } -} - -/*Parses infix expressions by precedence climbing - * console.log(stx); - See this for more info and an implementation in python - http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/ -*/ -function parseInfix(tokens, minPrec, lhs, linenum, charnum) { - if (!lhs) { - lhs = parse(tokens); - } - while (true) { - var cur = fst(tokens); - if (!cur) { - throw error.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - var opinfo = typ.OPInfo[cur[1]]; - - if (!opinfo || opinfo[0] < minPrec) - break; - - var op = addSrcPos(new typ.Name(cur[1]), tokens, linenum, charnum); - var prec = opinfo[0]; - var assoc = opinfo[1]; - var nextMinPrec = assoc === "Left" ? prec + 1 : prec; - tokens.pop(); - /*remove the operator token*/ - var rhs = parseInfix(tokens, nextMinPrec); - lhs = addSrcPos(typ.makeApp(op, [lhs, rhs]), tokens, rhs.linenum, rhs.charnum); - } - return lhs; -} - -function parse(tokens) { - var charnum = fst(tokens)[2]; - var linenum = fst(tokens)[3]; - var toktype; - var result; - if (fst(tokens)) { - toktype = fst(tokens)[0]; - } - else { - process.exit(code=1); - } - var token = fst(tokens)[1]; - tokens.pop(); - if (toktype === "stringlit") { - result = addSrcPos(new typ.StrT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "left_square") { - return parseList(tokens, linenum, charnum); - } - else if (toktype === "lambda") { - return parseLambda(tokens, linenum, charnum); - } - else if (toktype === "integer") { - result = addSrcPos(new typ.IntT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "float") { - result = addSrcPos(new typ.FloatT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "identifier") { - result = addSrcPos(new typ.Name(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "constructor") { - result = addSrcPos(new typ.TypeOp(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "truelit" || toktype === "falselit") { - result = addSrcPos(new typ.BoolT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "def" || - toktype === "let") { - return parseDef(tokens, linenum, charnum); - } - else if (toktype === "deftype") { - return parseDefType(tokens, linenum, charnum); - } - else if (toktype === "defop") { - return parseDefOp(tokens, linenum, charnum); - } - else if (toktype === "ifexp") { - return parseIf(tokens, linenum, charnum); - } - else if (toktype === "left_paren") { - if (fst(tokens)[0] === "lambda") { - tokens.pop(); - var parsed = parseLambda(tokens, linenum, charnum); - tokens.pop(); - return parsed; - } - else - return computeApp(tokens, linenum, charnum); - } - else { - throw error.JSyntaxError(linenum, - charnum, - "Unexpected token: ``" + toktype+"''"); - } -} - - -function parseFull(tokenized) { - var ast = []; - var typeBindings = {}; - var current; - try { - while (tokenized.length > 0) { - current = closure.annotate_fvs(desugarer.desugar(parse(tokenized), typeBindings)); - ast.push(current); - } - return { - "ast" : ast, - "types" : typeBindings - }; - } catch (e) { - if (e.stxerror !== undefined) { - e.stxerror(); - process.exit(1); - } - else { - console.log(e.errormessage); - process.exit(1); - } - } -} - -module.exports = { parse : function(str) { - return parseFull(tokenizer.tokenize(str)); - }, - tokenize : tokenizer.tokenize, - parseFull : parseFull, - }; -//var istr = fs.readFileSync('/dev/stdin').toString(); -//var testParse = parseFull(tokenizer.tokenize(istr)); -//console.log(testParse[1]); -//console.log(testParse[0].map(pprint.pprint)); diff --git a/pprint.js b/pprint.js deleted file mode 100644 index addfd76..0000000 --- a/pprint.js +++ /dev/null @@ -1,102 +0,0 @@ -function pprintName(ident) { - return pprint(ident.val); -} - -function pprintFunc(func) { - if (func.p.exprType === "Name") - return "(lambda " + pprint(func.p) + " -> " + pprint(func.body) + ")"; - else - return "(lambda " + func.p.map(pprint).join(" ") + " -> " + pprint(func.body) + ")"; - -} - -function pprintApp(app) { - if (!app.p || app.p === undefined) - return pprint(app.func); - return "((" + pprint(app.func) + ") " + pprint(app.p) + ")"; -} - -function pprintDef(def) { - return pprint(def.ident) + " = " + pprint(def.val); -} - -function pprintIf(ifexp) { - return ("(if " + pprint(ifexp.condition) + - " then " + pprint(ifexp.thenexp) + - " else " + pprint(ifexp.elseexp) + ")"); -} - -function pprintDefType(stx) { - return pprint(stx.lhs) + " = " + pprint(stx.rhs); -} - -function pprintTypeFunc(stx) { - return "(" + stx.name.name + " " + stx.params.map(pprint).join(" ") + ") = " + pprint(stx.type); -} - -function pprint(expr) { - if (expr.exprType === "Name") { - return expr.val; - } - else if (expr.exprType === "Bool") { - if (expr.val) { - return "True"; - } - else { - return "False"; - } - } - else if (expr.exprType === "Integer") { - return "("+expr.val+")"; - } - else if (expr.exprType === "Float") { - return "("+expr.val+")"; - } - else if (expr.exprType === "String") { - return '"'+expr.val+'"'; - } - else if (expr.exprType === "Name") { - return expr.val; - } - else if (expr.exprType === "Application") { - return pprintApp(expr); - } - else if (expr.exprType === "Definition") { - return pprintDef(expr); - } - else if (expr.exprType === "TypeDefinition") { - return pprintDefType(expr); - } - else if (expr.exprType === "TypeFuncDefinition") { - return pprintTypeFunc(expr); - } - else if (expr.exprType === "If") { - return pprintIf(expr); - } - else if (expr.exprType === "Function") { - return pprintFunc(expr); - } - else if (expr.exprType === "Nil") { - return "[]"; - } - else if (expr.exprType === "Unary") { - return "("+expr.op.ident+" "+pprint(expr.val)+")"; - } - else if (expr.exprType === "Let") { - return "let {" + expr.pairs.map( - function (v) { - return pprint(v); - }).join(" ; ") + "} in " + pprint(expr.body); - } - else if (expr.exprType === "TypeOperator") { - return "("+expr.val+")"; - } - else if (expr.exprType === "TypeVar") { - return "("+expr.name+")"; - } - else if (expr.exprType === "TypeDeclaration") { - return "( " + pprint(expr.expression) + " :: " + pprint(expr.type) + " )"; - } -} - -module.exports = {pprint : pprint}; diff --git a/prelude.jl b/prelude.jl deleted file mode 100644 index 2099588..0000000 --- a/prelude.jl +++ /dev/null @@ -1,118 +0,0 @@ -;; This file declares the various types used by intrinsic/prelude definitions -;; It is sort of special in that it doesn't care whether there are any associated definitions -;; just that there are type definitions for that particular binding's name - - -;; Type definitions -deftype String (Vector Char) - -deftype (Int) Intrinsic - -deftype (Float) Intrinsic - -deftype (Char) Intrinsic - -deftype (Byte) Intrinsic - -deftype (Void) Intrinsic - -deftype (IO a) Intrinsic - -deftype (Vector a) Intrinsic - -deftype (List a) - (Empty | - (Cons a (List a))) - -deftype (Bottom) - Undefined - -deftype (Maybe a) - (Nothing | - (Just a)) - -deftype (Either a b) - ((Left a) | - (Right b)) - -;; List functions - -(: :: (a -> (List a) -> (List a))) - -(map :: ((a -> b) -> (List a) -> (List b))) - -(head :: ((List a) -> a)) - -(tail :: ((List a) -> (List a))) - -(!! :: (Int -> (List a) -> a)) - -(take :: (Int -> (List a) -> (Maybe (List a)))) - -(drop :: (Int -> (List a) -> (Maybe (List a)))) - -;; Optional functions - -(maybe :: (b -> (a -> b) -> (Maybe a) -> b)) - -(either :: ((b -> c) -> (b -> c) -> (Either a b) -> c)) - -;; I/O functions - -(print :: (String -> (IO Void))) - -;; Operator definitions - -defop 1 Left (a + b) - (add a b) - -defop 1 Left (a - b) - (minus a b) - -defop 2 Left (a * b) - (mul a b) - -defop 2 Left (a / b) - (div a b) - -defop 2 Right (a ^ b) - (pow a b) - -defop 3 Left (a ++ b) - (listConcat a b) - -defop 3 Left (a == b) - (eq a b) - -defop 3 Left (a > b) - (gt a b) - -defop 3 Left (a >= b) - (gte a b) - -defop 3 Left (a < b) - (lt a b) - -defop 3 Left (a <= b) - (lte a b) - -defop 3 Left (a && b) - (and a b) - -defop 3 Left (a || b) - (or a b) - -defop 4 Left (x : xs) - (cons x xs) - -defop 5 Left (f $ x) - (fapply f x) - -defop 5 Left (f . g) - (compose f g) - -defop 3 Left (a | b) - (bitwiseOr a b) - -defop 3 Left (a & b) - (bitwiseAnd a b) diff --git a/representation.js b/representation.js deleted file mode 100644 index fc8f7c5..0000000 --- a/representation.js +++ /dev/null @@ -1,404 +0,0 @@ -var errors = require("./errors.js"); -var _ = require("underscore"); - -var Expression = { - display : - function() { - return this.exprType + " " + this.val; - }, - type : - function () { - return this.exprType; - }, - linenum : 0, - charnum : 0 -}; - -var TypeExpression = { - unify : - function (t) { - if (this.expr === t.expr) { - return t.expr; - } - else { - console.log("Could not unify " + this.expr + " with " + t.expr); - } - }, - isTypeExpr : true, - linenum : 0, - charnum : 0 -}; - -function isTypeExpr(x) { - return x.isTypeExpr !== undefined; -} - -function isIrregularTypeOp(x) { - return (x === "->"); -} - -function flattenTypeDecl(stx) { - if (isTypeExpr(stx)) { - return true; - } - if (stx.exprType === "Application") { - /* it might be a type application so recursively check it */ - if (stx.p !== undefined) { - return _.flatten([flattenTypeDecl(stx.p), flattenTypeDecl(stx.func)]); - } - else { - return _.flatten([flattenTypeDecl(stx.func)]); - } - } - if (stx.exprType === "Name") { - /* - * Either it is a type operator - * or we assume it is a type variable - * since it was not capitalized - */ - return true; - } - return { - failed : true, - stx : stx - }; -} - - -function isTypeExprRec(stx) { - var flattened = flattenTypeDecl(stx); - for(var i = 0; i < flattened.length; i++) { - if (flattened[i].failed !== undefined && - flattened[i].failed) { - return flattened[i]; - } - } - return true; -} - -function App(func, p) { - this.func = func; - this.exprType = "Application"; - if (p) - this.p = p; - return this; -} - -function Closure(bound_vars, free_vars, body, env) { - this.bound_vars = bound_vars; - this.free_vars = free_vars; - this.body = body; - this.env = env; - this.exprType = "Closure"; - return this; -} - -function LetExp(pairs, body) { - if (!pairs.every(function(x) { - return (x.exprType === "Definition" || - x.exprType === "FunctionDefinition"); - })) { - throw errors.JInternalError( - "let can only be used to bind things to names or functions" - ); - } - this.exprType = "Let"; - this.val = [pairs, body]; - this.pairs = pairs; - this.body = body; - return this; -} -LetExp.prototype = Expression; - -function UnaryOp(op, v) { - this.exprType = "Unary"; - this.val = v; - this.op = op; - return this; -} -UnaryOp.prototype = Expression; - -function IntT(v) { - this.exprType = "Integer"; - this.val = parseInt(v, 10); - return this; -} -IntT.prototype = Expression; - -function FloatT(v) { - this.exprType = "Float"; - this.val = parseFloat(v, 10); - return this; -} - -FloatT.prototype = Expression; - -function StrT(v) { - this.exprType = "String"; - this.val = v; - return this; -} - -StrT.prototype = Expression; - -function BoolT(b) { - if (b === "true") { - this.val = true; - } - else { - this.val = false; - } - this.exprType = "Bool"; - return this; -} - -BoolT.prototype = Expression; - -function ListT(xs) { - this.xs = xs; - this.val = xs; - this.exprType = "List"; - return this; -} - -ListT.prototype = Expression; - -function Nil() { - this.exprType = "Nil"; - return this; -} - -Nil.prototype = Expression; - - -function FuncT(p, body) { - this.p = p; - this.body = body; - this.val = [p, body]; - this.exprType = "Function"; - return this; -} - -FuncT.prototype = Expression; - -//Wrapper for function objects -function OpT(operator) { - this.op = operator; - this.val = this.op; - this.exprType = "Function"; - return this; -} - -OpT.prototype = Expression; - -// Applications separate from other types -function App(func, p) { - this.func = func; - this.exprType = "Application"; - if (p) - this.p = p; - return this; -} - -App.prototype = Expression; - -// Names are not types -function Name(identifier) { - this.ident = identifier; - this.val = this.ident; - this.exprType = "Name"; - return this; -} - -Name.prototype = Expression; - -function Def(ident, exp) { - this.ident = ident; - this.val = exp; - this.exprType = "Definition"; - return this; -} - -Def.prototype = Expression; - -function DefFunc(ident, params, body) { - this.ident = ident; - this.val = this.ident; - this.params = params; - this.body = body; - this.exprType = "FunctionDefinition"; - return this; -} - -DefFunc.prototype = Expression; - -function If(condition, thenexp, elseexp) { - this.condition = condition; - this.thenexp = thenexp; - this.elseexp = elseexp; - this.exprType = "If"; - return this; -} - -If.prototype = Expression; - -function TypeVar(name) { - this.exprtype = "TypeVar"; - this.name = name; - this.exprType = "TypeVar"; - return this; -} - -TypeVar.prototype = TypeExpression; - -function TypeOp(name) { - this.name = name; - this.val = name; - this.exprType = "TypeOperator"; - return this; -} - -TypeOp.prototype = TypeExpression; - -function isTypeExpr(expr) { - if (!expr.exprType) { - throw errors.JInternalError(expr); - } - return ((expr.exprType === "TypeOperator") || - (expr.exprType === "TypeVar") || - (expr.exprType === "TypeDeclaration")); -} - -function TypeDecl(expression, type) { - if (isTypeExprRec(expression) && - expression.exprType !== "Name") { - throw errors.JSyntaxError( - expression.linenum, - expression.charnum, - "Left-hand-side of type declaration must not be in the type language" - ); - } - if (isTypeExprRec(type).failed) { - throw errors.JInternalError( - "Right-hand-side of type declaration must be a type expression" - ); - } - this.expression = expression; - this.type = type; - this.exprType = "TypeDeclaration"; - return this; -} - -TypeDecl.prototype = TypeExpression; - -function DefType(lhs, rhs) { - /* Both rhs and lhs are expected - * to be fully desugared already - */ - if (isTypeExprRec(rhs).failed || - !isTypeExpr(lhs)) { - throw errors.JSyntaxError( - rhs.linenum, - rhs.charnum, - "Illegal type definition, both sides must be valid type expressions"); - } - this.rhs = rhs; - this.lhs = lhs; - this.exprType = "TypeDefinition"; - return this; -} - -DefType.prototype = Expression; - -function checkName(exp) { - if (exp.exprType !== "Name") { - throw errors.JSyntaxError( - exp.linenum, - exp.charnum, - "Expected a type variable (an identifier starting with a lowercase character), got " + exp.val); - } -} - -function DataType(name, params, type) { - /* Params is a list of type variables - * type is a type expression - */ - if (name.exprType !== "TypeOperator") { - throw errors.JSyntaxError( - name.linenum, - name.charnum, - "First element in a data type definition must be its name " + - "which is a type operator"); - } - _.each(params, checkName); - if (isTypeExprRec(type).failed) { - throw errors.JSyntaxError( - type.linenum, - type.charnum, - "Body of a type definition must be a valid type expression"); - } - this.name = name; - this.params = params; - this.type = type; - this.exprType = "TypeFuncDefinition"; - return this; -} - - -/* Applies the function ``name'' to the list of parameters */ -function makeApp(name, parameters) { - if (parameters) { - return parameters.slice(1).reduce(function(f, ident) { - return new App(f, ident); - }, new App(name, parameters[0])); - } - else { - return new App(name); - } -} - -function makeGensym() { - var n = 0; - return function() { - var x = "G"+n; - n = n + 1; - return x; - }; -} - -var gensym = makeGensym(); - -OPInfo = { - "::" : [2, "Left"], - "," : [1, "Left"], - "->" : [1, "Right"] - }; - -module.exports = - { - IntT : IntT, - FloatT : FloatT, - StrT : StrT, - BoolT : BoolT, - ListT : ListT, - FuncT : FuncT, - App : App, - Name : Name, - Def : Def, - OpT : OpT, - OPInfo : OPInfo, - makeApp : makeApp, - If : If, - DefFunc : DefFunc, - UnaryOp : UnaryOp, - Nil : Nil, - LetExp : LetExp, - gensym : gensym, - TypeVar : TypeVar, - TypeOp : TypeOp, - TypeDecl : TypeDecl, - Closure : Closure, - isTypeExpr : isTypeExprRec, - DefType : DefType, - DataType : DataType - }; diff --git a/server/.app.js.swp b/server/.app.js.swp deleted file mode 100644 index 0310961d9b92c36b50ac6b2cd35dff567256a42f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2zmMER6vrni6G8$sDPIzZeQ3{KNFs$CD`*G;afk*)sxWKM?)l>Nn6bTg$K{~n zpP)-en*0MuASjV&_|a1ECqxJug!sO(eOSkaq@W3UtNX6kZ@zx>=JRHY)y;JL-W!{A zH5x0t&M5W8otJLh|N2jL=B!dXrsC*BUsbK$t%tgl`WOl0H{a5WX{zJOxTSHiF3V{9 z(WZHX8N?z4guqGyO+8z`dP-e-@df`?zi|E>J@fRtE3Fa~0zyCt2mv7=1cZPP5CTHr z|4E=OkEu_vwBz0K{Eq{CKGxm$*X~v>LO=)z0U;m+gn$qb0zyCt2mv7=1cbn2NI<7b zojsw{uMq$LzyJOJ^J%5Nfj)yif;ORNp$pI-Pb&2j^ds~Y^d)o`+J$aF??cZ)znoI) zTj(CN2Ymnq&_(De==Ud-`VIO4`X2fm`V`X8CiE)wGPD6b4;_cTJBhiV1e!vxLl>db z&`Ib7gm4ITL#czc4MpTk z6**I+#)W}#&br_*jB~DaQ-z2|?MJ$Oo34z<-Vn!llpmvd%aDJPN%u)%%Zr8rZVBIDUv#~1+QLZqQdOfYqYPBx-EW7 z7in%>4~)n88Bc-B>DWx@^7t~>wA9Y8V}evW^cph_gSTx>*KJdzjQ1ZUteid3b+W}t z2?fy1x*hFOs_oIT`fTVg7Et+mvLp<21vFK#h6xX63}P(ZRl$h-bx=zXBbcF~yF>qx zoTaX}qHUWM;mwq1bF1{rU-eIuJ&~;PHv%-KV;LQ7$9}YAB)kX2c zZOc%@AQSKMrc{de7W&O!gtprucZ;LGpNL~CHJLME5XH_mHBO+n9fyx?zQZeReuPW) zzQ5ZvG;?&l^i5?aCmc3(1%x$lRwuNqEk-tkQ0C=hH`$g#b`k?lnB8i5wG)b!NsbllU` zsjl81MGFMPBBWdpLL4j*;S>-Yh{6dek+>iy7cLQZ5J(6JLb-rM0^h6Z>h78SOAa7} zYUIy5-Tms-dtbeJRrPxM_kHHVCH_$NK8DXB#?Jll6Q4Ww%QxAf4>GnU3%a}Sr!Yca z-&cyUFF|4Nk&9y7ABbKd^{UjpI8{ZdWzl`&t@ZU5x(OnIfxy5t1Em?Bc<2uHz{&gV zRKF)W!tcK8>a)p@~ zJP$kr7~nDx0dE{+>^0z3;K#tzz-NJv03QHu1Ag@`^anf-JPUjS_!{su@D(5iJ_&Sz zdw@T_ld<0cF9P2OHi7fN?ZC}*Z0kAli8z;nP2pa32PW`Td8 z81rY~H^2+Pw}CC-tH8s+0pJ#ZiZ(QEfAK|{J>si(oVEY4O~!jY+@UXAOH=BMXL1c+ z^X^&qn~a&hDzm}zs?bG;54Du^H4*((;<_;F9lmsJ_B5JLKI8LzxjRUPL#bsJ%bDeF znI%uo)NN-wyisi1lL_?cYbmaiLi*J5&^KHyX3$}`uLc{o1qn1tAhAS`^KLSbndw|} zI$}{s9xaqvY!a14rx>-G>g8xxt{a&R8uL1^ewYe_yC7h&v5d}V>rUHNHFBvmR;*<^ z%yVsbGas6G)ea)oe39s)I~Ms2b?J4%;?4F&JzCVn`s@C0$qy@+IgvKYpJL?p6k(Gc zGJ5X#x+smMs#r@*JhCdlQLYy^a!I-%N~YIDY!8iQU~HHy8?+?r{4i5r?z7q9QPhy@ zZ`0o@B*k3Bqq%;|xk{+(gQfr05f8;`Dq|QWop02$~G*-3IN9N~wM1$m?G0DH9nu1Rpe4d}!MI<0GRQbUT@CXiv=K%VI2dp2fa>9X8F>T=KaiR@oq- zM1cI`@4>tb#Ll`j#_^FUa)zHUd#NRLpF@0;)xw+!+w^9M!qMn<;rb*>h zwFJG1lY+kYmSE$b7p+61>Z|h0P4f%Gn#zjx7H8zvaMBYp&)!0pjie`%hPau>Ha`?Q z3g%wQS#c)M(9~bPr!>@+iMD)FV&2{4hCFu4Y1SOzT;i z2tc12DNuZQlQmp>+$x@_tuYhQ03FNfl%gBdn z%p>F*sf$=?8J+gej#kgQJp(@Jm!ZuwsKpOQYXN&XA>a~eEl}mvwhHWU>c{ww-=1R6 zU_;O;Vm4bMu_0*}lBN~UN3@k#OVX70B_F5^DP7TQZC<% z;C#9P8T!%di8L7+BwAG(o-6Dyh@y0(i!S*YC{GNOBby?3BC?$v^+Fr0*4mL|9F*m* zLzB?@0`7U4^CW{^f)9kDgse++ugP#TB5M<57_7wwtidW{dnG4_*ml4k>!TXhs{%a7 z4|EG;OtOboKWxv)7r$(@1mrqAb&ilPkXIQb%L2|0X{A)^I<3Sok^FI1psx%mz3B1< zrN<)W7)@NmG^{5udnH+wnU!sPw?;$Us>w@DL5I$UPAneD*!JUzB&)}?m(zTNRn~Ip zH%BYd6tqUCa$u7Jh58Bb%`{ylQBVz7noY$+{J=j!-+&<02Ywv zX@Z_W6|9URh`#pqfS=hk=?Z0Y3%7pON7@I64|p94PyegJ$E_yTYd_!Mvgm<8?yjsYJ9 z4gr6I{eJ~s1Gaz?xB`%0mw@mI3IPNb6-=1-5l&TWzG`g}_m0o(`O-CQz*crHewxC{WbL0&4`_gL&>Pi7y9M z6&VzkT&1mYW2#_NKjyaRjDiz7Y!gFF*tZ%~i*lM=C2EJV*2J3;Z%18(YIWs0BaXoF zZXH&STg68zl2N6@7SncXRtwY(EzwV5!0EHUSyj<<7H zO{k8F>d90iTkvm(`9gIppRQu=Va$|DJA?MM!?}^u%Qdv05Vtq&8@K6+`F5T0rQzMG zsP08T?OL5>ru+4;Md}(PPW&heQ6bJ1N(_}as2H>&D7O_vZ6{96f3%m Oo-K5syoe%3!Tt?A7QRCO diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..d9568ca --- /dev/null +++ b/server/.gitignore @@ -0,0 +1 @@ +*swp diff --git a/server/.parse.js.swp b/server/.parse.js.swp deleted file mode 100644 index a1afa1017d0b2ace1474a9f231908d4893617592..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45056 zcmeI53z!^5oxn$gQ$SEa1s|uK0g~OYnaw7M5J;4SS0Et)5*7CHWhcA6yF+GYmg(8- zZbE{BfWgNpN>or$`FtRt0)nS}aK<}9d8sHq?l{zgLkM^$qM#V@e*b!OSNHThc5`@l zeluTwneFcC>Z*TL{j2`}s_I!c_bp48dq?KxX861et~%<>p>IBydD%gk%(x%O*`}YM zny;*H8Y+|7LWJEXFUyat8_0JDer1DS=^o8j0zY?lYY%GS8SNl#3A81UB7w2$;G84( z$;_YEqni4`*%{se`>#$3*gn;kKwAQB3A829mOxtqZ3(m`(3U`30)MR%sE+QLIgiZk zW-@q@`F=s-drxz`(R^=BTz|1S9x>l9G!fW%b~op(p+B0qzK6Mfw)uW2as6-1`J(w= zZW3(ce~~%gW4^zZxW1P;zruV!mbm^xbAEsGeUv$2<2R?lCUZNy3*HHXa6HU`S?~(j7yg9d|3`Qhz5^eJ^I#adVK#KYEZ7r%jicj- z@LjkE?uIYG2cQT;;KKmy4-eq@xD3vNGhsgb0cXVT;C|Q+H^L3D4K~6C7=bs#0q`B1 z8{dNK;98i3qu?O;9gdMl;6bp<$rBn-n4Oy%Rv?#_6#JwG>;^NuMD_@$Z? z)xu!GuPpNT%D6TVBuW)E_?T&8=rx2jU`1Fu^4)bbL~pBSyInjH1Lz~@B1 z>JND9CcWygPmuK_Wu0Fg_x%$2*_`pbieDY8l=uq9iq+s~&d6CguTJDf$AaMw6>*2U zJ?QL|K!riCV?(}J80Z)bs^OJRZxh#a1QJQ=Cp%UmiGIH%%r6aiZS8^wxFmT;}*L(Q@aSfI$zLzJZg^~(bESE=lw$7%_to`=9brnCqUSuR6d8U?I zuIQJBs>9wf3%wrwWVs&QCP%5C?CR;tOQP!^&R0rfBU)H;qOQP-g_7@t^oxP7ic@Zi zlG#62sraR;x6pGW**kZQn_=flT25;OG{aU|RcNN>b>{5Z&M1;5wKAU6+UKNISsVHI zaG~hiN*$C25|z5PAQyQ(-prY<804^Cqv-A)$*-qPj!~Cri&CS6s#o;$LDie58)wvv zGnuqDIG~zHR2q`unvYvyRNY(P_4Q>Bb4rEsIxIVD*7M!q!YZT_thC4gH7BM{8f%k` zheRv-jsXcON2V4KQ?IIba;{OmoPxZjrjTMyrf$P>nqZm=8XPP2R}1Bm&gAlZX;SOk zu27SA=~~rg>PT1Es6CSaU5A&Hi$&BbbqHN=WmG89G2~0swn~0dX)&$w1Fuk}lj)wF z=sm_t)k0ClFk0~k3OZ$deX3f|n&l1V3&p@IS5%1cO1U)TRi&>f1g4C1ud-RI1Jk(# z)rqh%dkYsX^f)1RNgxx%3Za8bk{f&Mp?pWAH(Mh5Sgy*A5+Wm|8h;LzotmwlP(qof zMNg1e^c+XA%T0Bno{+XZS}BhPxu87acZBKdnB)$ViOG(M&Z9T0CYsDvJX4|yREGRY zhl*65>WQ)@la$OLg(D(09gZ%$zCIOn)+|+QMsR_b_rkPPhtVfh;+C`0_mB8hzaoXM zr4>rMS{YN)kp?Qy4ND=<2@%`o&QACIgqEp4QC%fhr55X?CWWE0sT(PsR&`ZsH=&zj z-R3g4Yi?JQF+#&;R4P|bpe2;Y{ei`kMvF_65z%(p78AB1k$m@TRTxU}(sm^2X0Svd z5FfQrM<^pH8mNp}`ucQ~Gztnt)kah3)u6W;nC^bgJTz2TK&o2_^dr3!ebZC}zrW1r zLaAzRuu>k;4Y)8gT=fD*kMcB07Aub#k~Df)kNYsC?`s}5Sg6q5Oz&B=J}G{_az>|# zGA{@A$X+yB$y_u?a#5-Ba=-;W;#*k`!UD3o)G9ZcQ7E_kz`z-mehJO9BQ;oaOF}K! zL@sbUX-1B!YTHD{FY1w^DacI()Roof8P9&An9W}*N_(5FWZnY%mkhsDrB#9tymQYr zy4;QmMJvvgiV^0y1qn%Zl}IaSd4x(e3d%)4S1b=5ohgirmMc}SzgSjd4ppzRxo&eD zunIjJ22#UkUG)f}j^Y7EN7W;2B>FHG#Q^rg5JQ?u7>zj-3#GDO*yx0^XJWzDnn=b< z1AZmwXZ#(d^^ouZ)pEHQPbPgsc(vlwfdvdz^U}HM=*9kjFShrSAojnV|K5R}FZTaU z@OiiZHo-WIK^0Dc-QXeY{2O2^jKLz90TSnr;8wUn;%|T25@<`HErGTK+7f6>pe=#6 z1lkg4OQ0=*wgjdkf$nZ=)kc3|-*!~}pt@4FQ}@noaG~y{HMx=eXos<5^_NU+)eGOV zMqLzRJAAOXHzWZkj1`O8iy?+>&Kk5Gg`ir|lV#RxV7`;i1a&%$3a3H%cQk7gMPcJ7 zoc%L;Xxa_Yt(zNP4&8v^^V70ra>e9~xEBWe!8{X(-X@)B5@j72xN0im(9nL`j8292 zrpVv6RHZEaoN_sg_(6~#@|FKof`rota!`Axx~C(%N+vZ68=Ky_I1j9F804&pZ|UA`cK13SO!_xiB10#xE|gQB{&661hM%K1+n{gVC!EG6VL@6 za1iWd-u_*1F>HV;1Wo?fPZ1G{tmbT${=(1b6_|45%cn2fYV_a%m5FbW={St zxDo>RBlGSuNB>EXx%sVdFff|;;4{2O!fH^Mb=A*_W%VFvtO z=HFpETml!th46Q<2)f`U@G#|f3w#xBhA~(HQm%7hmp@YD>VAyNPdBEzZfxtE%xKSF zx>ve4E2{(ae13LKig#MIAh-4>Q{~R;%@Zw^3}BDlfZEF$Z|}=|+~$=L>yK6OCukDDF;g+wqCZ$&yRMR#8Gca+Hao^$stmnCghnH>MxHKS<>Nqv$Xij-nwFbcveQzOYtlx-y`{=$5j40{H!u}AR01Y zj^~`Q0&{vYu{4j+;*U16v`Z7bd8UA*qgz+T{c64TQ8l$^^aSJ4k;B@SWBu}z!k3Te za;?uz6|iwh7WChAu94Hf6~Ix>wm7+DrzA|Zjd~Ax zM9L>S&QcG(ETzDlrc9WQjus33x?7R?P9E%)M|~F5aKvn_nq-wZnmNO=HpEWUk@f*9JW{%43!ZPHCDd zNp@&czbLhyX)ac2`*8s&K`QZhB6FEtGcvQ%Z9#0*09(RM#U^2G)leCfiZ3Ty5L@#M z?!w}nUCzV|-F&6ZO2H9dYXuh$teRvm8_h)PVj9R-O<6hmb-ci;CRM6vjY581(QjVy zv)r$485v_X5?vOXV5KpYhFFXvV??H^`)P4m?=Y1|$!F?k%IZ~WLA_4deQ?uWIo6FK zAZdTi8cuB==IHuD&d;fKakdCYRFNo?jAT3PemU7+9Yf8h6$wElcXj*X|Hu8Esx&8* z%iiMWrO%@Yh5eiJr&WnO}Oz-8wIz&Y}l{Fk)(OM4rJ(0lT z^1!6i`PoyUnhOJ2C8@eW8!VwD^ffg`h(>zNG{bSBCZICubtZwA)|fk+YV)k>>A=_4wg)w<9wrEZ>4j#kC{B|EGw`6z z)_!8Ts`fHxw0^K%TS^eM9!tjSEAy3R!Bic}NF+7cBIkkcEIA`oisn$mih81wcvC;w z;BJ#9Aw}g?EA}M9*E7qA3TEneiK{>t6?{I7MuNJuoW(Z^WhzE8Z3b$ zK-TZigbX~4{eByK1dfM=FbBHeacuZ+z-7<{2g3od1N;4-;SfFZfSvbXjx19d3cI!@EJ&+|PjB z;V0PV*TCiQ5%@4{gUdkH-=765U@^P_4u=EbQSA0RLDt=00Bc}h*b80&Qf9ww@dX7^ z9}9y^(iB}QO;~Qv_VpD8S=-g0FUi;^F+@qOrtS3ffLQKK{luDl-4T9RQ5(hKEQd}6 zYkYgJ47##i+5Ym#NS^PadNn0phm3CYGg3!GViSnk5VX_Pn*@LNi?H zm!*UCheLJy$VArkq0#uVPBRF5iF%qg9=Ne=n(A98IVw*kN1dGwl&^D-N^vg0p!7R> zy5_698XLOe4e3y~v81(2IZaGP&0s>V=}ISmS(QkYH&xBKX7bK8^Os!HNfIx(EiLsp zYfPBLThsegon74N3!Nm6ODG&sH$Ldz0gLZ z>sKt`ocX$fwkAhAfMdmAMZ7;ai&*gLPhe{lC%ySz4=ZeP4ryUzud8;D>SRWeEg(HL} zg(peK9_!8>M58}(_hNL7snz&-Z(X4@fRn0e;YpOSv_#{DxL8Yj}nA3*JO)ERnLIrsE=A51(hm<&x)p{Xq?95fSdd_V$ zYb6Qf6P3Ij=vX<{m7;S?<#)IH!aN~?zMw$FUuaD@_4q(%W6AXPlttv!8v1S zWIYydI2zaDsQdr)r>D}SFl`yDPSh!5y_qN~k+j;@vSB7wF0IdrqVH1P(;6F1&;P$1 zQ~T$}{x9;ke7=pX|1lVaec(kP^Z$>+U2rE{3g^OE&;d_l^WO~D!jeu65T1h0jE!2Z7hJ_jF!EieI9SPv({Yv38|{kz~w*a*wv_3$c?efZB{ z?>`AQ!aHHL98+eGgOuIRr2JAo(k{Y!)Qb9AUI<3=RW@=Bh>w+_*)Us1)c(eiLLjpc z(P?H)ne|hxH=59DLH|3=Al$UxU>CL<+)mR=b4u)7$D`?nwB5K?F7D_qk^*Nj;xLV5 zmPq?Ery?!)ar2w1Y&W#ss$W-Y=@F>aHg$q2kLR&w1l?lTRX7X-8#b1I4w8;ft#{po zH`5DGhIdB=SVu7Q!heBkyz7&dj%39l z?;MH=SI5Wfj0shdEiEDIaERH%iWyl8Ac?bmu{wwk{KB#-;d+*`k}(mB&1BPcxH<%H zac;#*;xFT)n5g36SfhxerSZnDpmZ2^i zOhetGI;Ctfl3?5PRdXgeYjg78a^QCyl4F3`<+=N*d$Z0MS1c(b&(`%E=*LcpQ!hm4O}}xx+=B8?>beLTy_K>zAhs1vO8tZQ27BByGQ6IYC)drXCvD|8OZ+KtBd zYOPYJgjBjs7UhvD_E2p|hDd%~L&(W&s%|jtNhi)G(SD1R>U^?G2i;yp*(Zfke{qcM z`>fzly*X(r72AJKqNCUs?xTc>@Zv>*9s1>w3c9nnUWKnJe*KTD$e z`gk6bppLmMuho!AfxbSG8P^D5^|SNVBwB4VEhpKosp55qKoT}qy+vm3+q~+HDJ7X! zYBK--3vA=<*vvBjZ{MH)1opnz|J&eFct89-tbvo@rSLUu{+nR}&W6)qImmkeWgozP z@EErLcDNAEgR|gF=z&AvVE9*T{_XHtD1yA>??~7aZoIxEekR6VL;%gIB|E$n!Tr_61x41(5gp9ShIm6Zj=O1lwT(e8|HB zcnY7u&*1_13ap2>!76wqh>zeF_$quD#^EG54m|i3eu2l}4%h~l!YC|;MQ|Ye8lS)e z@M(A-OhN!>!y92f%m!Is@F4zykAkcx_#j*gAAoZp5Atq5`8|Uk5MRPg_zpe>+h8kf zfHUEASPZWPPf#DJRneXi)w9by82(j%Kspxm5laH_7!XV!bH+BfEH(s-A7y6_e=OE6 zV!dz=BaKB)a)~c(ks9SIaYkB>tNN9D=6zOSBZ}T{W!~VCQwtNA<6JwqA?OHSzmYS4 z>32wJm4G%H5GCy-%5F?DZ#`40LW0@%ku1`0BSDE&CRMhjLp5oT?8>1VA3A80l7n0z z6C8_+A?&1;@fO=DrNrs31s5@-eq80Q5~|*3h8LLwNkdDoGHY$<=V+KvS6WSJ$}7d@ zv3G^z8(kqJhK%GW5rdM2T3Ig_YqfMZ`U+6BW|LX75tXfiwXr4omT)*_mVf9n9(V5UL>lkV}ry=N!UW3Uh3R6+S5;mSOU8u zBgZJ2ej-jNmh;tJDyl(=VHb*HX=&GNt_WT4bUE9xt~62{b2ZOdE6F5AXUuTHcq z0$6Ki-BJ?WViP-~T4}M^YIG|b8)TD1*obNsceF<~+UY6{&F-9y&Zh2vRr%gT)6_x> z6;HzPDlIk9MQC|QM;?hm_4m5Fl{@6nXcBrT*Ofb8Een(DrpHZOkG&61)eTd8@>JKC zh38S8q*JfmkkO7XbP*f4*DKFs8T+G`0BTFv8b_J9`=#8CR%T44G8nlx*|gP9)2hB!X^ zCDU5KCM*xbGg`(&5?zvj#AdG8x9`g1Sdf#pbx!Fy#&5*pNGPQ#oNQ-gjxOl# zrrXV7(GFF3gZF5WEw#B4`*7#Y?U~m-_sH(K^VCnwqgduJz@qia6h|;;-Q*mpFnU4O zoc>~AgykzkvSs%SU+Obco4Clm5qZzGDn8lJh}Vi&2o`-=u%>rG;*TAjtPYn;@@{jh zg=GIeTkL5h-LqF}CqGfd=2&=#_N2S&$tJ)Z{M%|_#)0WAT{Uua27R_nV>YhHQnbm@ zwb=hNG5w#G`D5(=5i^JU6YP6=@82Yx3{Q$J4>ITf4tP6kfz2TM|7XKNuopasP5&pc z>*0&=4v>8TIoKWk3%mYt_;>gQTn@7T|5TU_d%z3eer)d+hhiVH;co1$aF? zi`_2s|DS;g*aM!xPX7UX0VZK7yb5l|Cch1a;jJKh0an4`@N)PqHuzI;3tSDdpT7?l zz!5M9_JT*S!MDS$Abb124i|&W{V##}a3~xCQhvXyvj)Hvsq>}Vq6}X}3+AL{$naCU z?d7l7ZrP010Ew=TP>Y%K5H%obP9meW=SRZrVm5lzhTE&9ni+9*AX}*<74?TPwr8}B zL@IX8r`F3_6ND|I?mOOHn~UB5#$RERk#Rh+4Idn;D&0M$JXM`)^ym{3TmN}>vgztV zbTo23CuzcHB`PVf`hyXD-J~wA^!eR@qzeN%Ev@?YEeWEX-7!m4Y4l%27iluP@?DI@ z5*4w%hOyxqM(LJYTEVCSC7NC6Hj|1J`!ue~1kJ8ur6>KPEbo-JC;SCgH%e_t&h^wC zyQsji#uUq+K5%1fw3e}@$fmW5QH`q7cNEn&?IwkiJ(jUZ_?{G*7mi*(VoS=IqEN5? z)^ijKTlkR!S613H+p_FcCS9GBSl43bh8M<6^OW+^r<@&=$qd`Kt(fdKU3a#NnNqhq z9i^8&l{%_&kF^4z_DcE^Kh$o|9I0WjR6P4%IbJ!j*+}tFBW^ou9*T&)Uiw zE@VjBv&~wm%)ztvI~t(7^M+xge4h4VO>KX7ohE3iLu0|mW)kW|q(x^}9;OCzmn}38 zD9ulYa>Q$fn(4s?0WWJ9e(8%MhsH!95|bw^UkiAriw`-R_e8;snk_ZF>RcY2uu`VC)9Yyiykeq zZY>_3v9_&!_^#CZ|HLrd9UD^Y|Bc2Tox4>`k6Z`^x1`onkSOD_- zelLPQ;4ctA!q4Gn@Ey1sw!&&S4Z2|;_!Yi`d*E8Q1WtoPK=uyY2wwtO2jGLu^~;`t zr{E#D13n0ALFV>lj$g`rZ#k~Jc(F-y;XQWF8}C$~J)FlM%w{m!P}4>ct}3K4hkMtX zj5p)=*ue@}km_!_XZ!9p^ZOxFA6!rS4Oa2g#oBt^b{@Yckt26GPiq}e-6D}i5@Nt@ zZdxvGPiQw>)J?t{SZ`}cbfzg@31?+{^b$nTZ)uz&In=;} zu17+suE%zO(Kv&v;sucqbsNoe{P?lFsrjw=Z#p)qFC<6o4{46J2Ui)e2e#7<2PgFS zflp>+}SotvgPrx9nFd;gl5~o6)J}6-Z|7U02ML!ee5`&P$bzZneLj=y?<2=BUN` zN0r0ZiFo`Jq%xrs=D51UZoW*)JzT2dX4_ilI?eH6krP{D91gsR%;kJg=eEtf;#2=rnLS&+hp5K9Lx4bHJGzitz22)We+pIW8K(U zqoZ==Y3rO^nL@pj;K{nDx3$YCiD5*zRMRx#FkQ(~4i^%*sWPQ(^Q5YdJkH!~2Klu= zIc&?>xiLdRr92o{^r~NbWD<*WdZ5-)juBC;2}qN0hjS`Xjek^FiOSmI9V!`W9)g6( zP)bY8j?2P|BA4_JRK{mfk!8Gg+U91TfOkYU!03(8wgU+JVPq=v|6+rlhOH|0{|aOO z@5I)B5blNRU=YrL6)+2)!M=YAz6YOx%V7g_!)rm-0?7LSt^;{5;5H~j2fPC0{ebc= zfKS4ELEZ;&3cL`0js5-v+zr>lW|)N4kcHR5PHgtO;12iqD3JFB-i!TyCwv>^_W*8(&%!p?3?&$ZC9nfIeILZuzYVT|_rb*= z?+*|;&VwVM{b@^}ErGTK+7kHdkpN>J^^x8@byrlA%k525?M+i^S4ex)l(C7_z_-y0 zab-*#+JOwTWnH1!|K8p-B@4#z!kX1I>0%maZE#2t!B=l;l9M@anqFe50rBP--qj6(OYLWXZ{=ip}qeA diff --git a/server/.prelude.js.swp b/server/.prelude.js.swp deleted file mode 100644 index 8dabff278ae88b4d25590ee6f860c26eb59be894..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 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 CSJX2A diff --git a/server/.test.js.swp b/server/.test.js.swp deleted file mode 100644 index e93383d57620c7c7189e5f382c3ae33ac6f19f26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI2O^6&t6vxXLKVvk+i?~QCYfO4{(zCO>Mnkef%t`TMHBlqOvi8o@>~^+4X1i-P zyXvZEHAcaMH%0IRJqV(xW~kN;+yu43$nNa^aTM=HH!c2z6J9z%n* z+wbtgsg_quMKUjvniQ#Y53jACHFRN3tO8bnehPGDd*{s?*~oBRP4#OBxAH4D-`CI5 zUb6~V1*`&A0jq#jz$#!BunJfO{-+Aa&N}uuVq0h8J8E9fTlRXsIls`nKC`UcoZ1(w zfK|XMU=^?mSOu&CRspMkRlq7>6|f3e1^$BycrC^b!LQfp0RX=L&p!YEa0O!@f@5G7 zjDZ30$K{Nj1aE;Q;DLw0ey|-}2eyIBzy|Q^M#jDZuYoQ&1P*|Ez&IEI*MMIxW9$q# z1%3p_!7JbxcntX9Zmz5s86H^6gX9!QXa z2Dk~_2u8sO7yuW5UoT=W=3I0lY_r$Gli0JebBc+m4DI04=T&w~!Q1?&ZTz;$37xE5>xXOKIT zKTl*2k=B;yoO^5eOYut)j>Drj(iL-EFK}ei6;(dhblY*VF9@8L-<0D?+^KRenc9~m z-eTMy_xvQSRQ9mGb!8j}sVl;cTyz=}WY+FRP3gxGS49W$!<5vi@JA3#?RtJNo)wY* zFkGQutfc(<8uA}4Cqj0Uh%dN-h^FNXzkx4iZ^y>QxLA-PYKfM)M!w8@Nq(7+>CRkj z=PXngmA_=Oh{8#?jTode=_csa=^!E<5E(2K3{(lVPCn&ckxF!t^IDCkF+bc*W#%!J z@hQ>tx~VY!@TM2-kbK6AT7lqlMub^iB@+*Piabutn z&u??(Z>GjxK1^cfBI}50%yd{JbU{$W+YO|4o&s2QOuBwcMADa9uVtllx>TvMK9}i| z8MC$*q(+`ThFZuz1$q6Rx_zyhag@e^aD#Z-NoAtOwXY#5g>d;+JXG;e%IZ;7c`NYiuSFzw z=yk}(kET-^FtSpi!AMWhxN~O~Dj5|gswq-QWZF;@wvb2pAZszq&}TzOAx^s5742IU zb1qMz0-VG_~LB_|glIcyu!3CC;uJt9O$ESj^QD)S;2tw zMtyj+%Im|sCMM2#_s|VAM$u_~czAWY;p*tfs#YUtZDcphOpteZq3A_;uNO^=)M+$E zMqoy*=`mR9g|k$tRNTX{A31}At3|0Jn2K?`#>&EXa{U&IN3Xp+3OdDZuB42!-5q6 diff --git a/server/.tokenize.js.swp b/server/.tokenize.js.swp deleted file mode 100644 index fbfdd98ef9002b37e6fef1c393527c4a85ebe94a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 diff --git a/server/.vm.js.swp b/server/.vm.js.swp deleted file mode 100644 index 73b1469ec2a7e4811e5606cfe36cc2cf0a29e024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2J!~9B6vrnK;wuTUKmt?oyilC&^R1IKhQmUUAd(%D6p+Z#aT0UBIeYQm?rL`S zoP#(NK~T`qra%f31%euoprN8bqJ;t}hyp4KBm@!?;y<$=zO@(MS)u?mEB(AXGjHF# z_kS~UKG~hcD=QahsjD;N@yt+iMlD3RnfK z0#*U5fK|XMU=^?m{4W(y(Gm7KGCP`OcQLyk*>lgD_GT5Z3RnfK0#*U5fK|XMU=^?m zSOu&CRspNPe^3G5W$en`jD2tqg2&(g^Y8!Po@DG(@D7N;d9Vte0LQ^64=~mRQ{b}` zjNJm)z&5xFYT!}u2zVI$dYrM(!JFU>a1(go0yqy=!3;PCem}<8H{fIN7Ptu{h(HKd zfCGNHpRqgOEATG31r)dhX241C$9)(FUxM3U8^quecnth}FJnJ}@4$!PeQ+BLz{}tz zFb(bk4EzS2egr>&@4+4LHTVc<4c`VGumq;TQD85tfK|XMU={c`DzMXJL}I}GgeyT$ zWslXpO1z+?7i_Tpxbd)?_@W`MMd1OK+0cQvo#GmeGYzANwunnlC>3=@k0-vO*BIMD zb{ZlnR3Zc7u`-_gSYUkrU;|PV240V9ctIy3UmQk)mY0{wSqYTb5YnOR*R{LRQF6}t zAy>}qKHp7p=V)zhjpkg;D)jW#-k%jcFYuHX1|=_P5=9z$#nSNL4I$P^1OrcoL0<%F zRwt27r1Q)(t@fZcMesKsbd;sp*2AD{;w#UWrhGtRE4@-eSv~wP+)5&ohSx>hWv62* zagp~$$*ImWy-FdYre(jGI=L}XFA3J`OtTXM#WE%5>~2mbTK%d?a8&oQ=J|Ha1lES4 zs|%bi?X=y9l6bSU-dbL}>?cdrbt&Eq6TeG(2~jVUwC;y-B1QZRoa%N>SI$G(7Mr*| zO+Ie(^XWp>L+O+lZ?$zCy30pP?`dBI8)~!3_T_cf_jU2hA?-;`zqFe}G>eD}KYB3? zYr0vdNQYvMs1Z%{Ic$~}W@+hAcEedX1u2w>752GNK}U>X#2j%Mi-!4mEV1IUT1?XWH$o#uZjAhr{G_JKe061}+S8y=xrv<$Jp5?2L4Ba;ej#9ojj_=fWX< zE==Ha?vOs`Ch$3bNT2iLe72ZgWZ9zA#YfHid`mnR3~G)FBVP=J@6_>iwr@UrF-|=h z_Q`3uc+NkLV*H=G)69*c2){*0lQ(mg_ms@cf-g+cO)xr<8b-ya6cNq_ Le8iZOICb+EL39b9 diff --git a/server/assets/bundle.js b/server/assets/bundle.js index 406ae04..c02fdf8 100644 --- a/server/assets/bundle.js +++ b/server/assets/bundle.js @@ -1,6597 +1 @@ -(function () { -'use strict'; - -var __TAGS_CACHE = []; -var __TAG_IMPL = {}; -var GLOBAL_MIXIN = '__global_mixin'; -var ATTRS_PREFIX = 'riot-'; -var REF_DIRECTIVES = ['ref', 'data-ref']; -var IS_DIRECTIVE = 'data-is'; -var CONDITIONAL_DIRECTIVE = 'if'; -var LOOP_DIRECTIVE = 'each'; -var LOOP_NO_REORDER_DIRECTIVE = 'no-reorder'; -var SHOW_DIRECTIVE = 'show'; -var HIDE_DIRECTIVE = 'hide'; -var RIOT_EVENTS_KEY = '__riot-events__'; -var T_STRING = 'string'; -var T_OBJECT = 'object'; -var T_UNDEF = 'undefined'; -var T_FUNCTION = 'function'; -var XLINK_NS = 'http://www.w3.org/1999/xlink'; -var SVG_NS = 'http://www.w3.org/2000/svg'; -var XLINK_REGEX = /^xlink:(\w+)/; -var WIN = typeof window === T_UNDEF ? undefined : window; -var RE_SPECIAL_TAGS = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?|opt(?:ion|group))$/; -var RE_SPECIAL_TAGS_NO_OPTION = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?)$/; -var RE_EVENTS_PREFIX = /^on/; -var RE_RESERVED_NAMES = /^(?:_(?:item|id|parent)|update|root|(?:un)?mount|mixin|is(?:Mounted|Loop)|tags|refs|parent|opts|trigger|o(?:n|ff|ne))$/; -var RE_HTML_ATTRS = /([-\w]+) ?= ?(?:"([^"]*)|'([^']*)|({[^}]*}))/g; -var CASE_SENSITIVE_ATTRIBUTES = { 'viewbox': 'viewBox' }; -var RE_BOOL_ATTRS = /^(?:disabled|checked|readonly|required|allowfullscreen|auto(?:focus|play)|compact|controls|default|formnovalidate|hidden|ismap|itemscope|loop|multiple|muted|no(?:resize|shade|validate|wrap)?|open|reversed|seamless|selected|sortable|truespeed|typemustmatch)$/; -var IE_VERSION = (WIN && WIN.document || {}).documentMode | 0; - -/** - * Check Check if the passed argument is undefined - * @param { String } value - - * @returns { Boolean } - - */ -function isBoolAttr(value) { - return RE_BOOL_ATTRS.test(value) -} - -/** - * Check if passed argument is a function - * @param { * } value - - * @returns { Boolean } - - */ -function isFunction(value) { - return typeof value === T_FUNCTION -} - -/** - * Check if passed argument is an object, exclude null - * NOTE: use isObject(x) && !isArray(x) to excludes arrays. - * @param { * } value - - * @returns { Boolean } - - */ -function isObject(value) { - return value && typeof value === T_OBJECT // typeof null is 'object' -} - -/** - * Check if passed argument is undefined - * @param { * } value - - * @returns { Boolean } - - */ -function isUndefined(value) { - return typeof value === T_UNDEF -} - -/** - * Check if passed argument is a string - * @param { * } value - - * @returns { Boolean } - - */ -function isString(value) { - return typeof value === T_STRING -} - -/** - * Check if passed argument is empty. Different from falsy, because we dont consider 0 or false to be blank - * @param { * } value - - * @returns { Boolean } - - */ -function isBlank(value) { - return isUndefined(value) || value === null || value === '' -} - -/** - * Check if passed argument is a kind of array - * @param { * } value - - * @returns { Boolean } - - */ -function isArray(value) { - return Array.isArray(value) || value instanceof Array -} - -/** - * Check whether object's property could be overridden - * @param { Object } obj - source object - * @param { String } key - object property - * @returns { Boolean } - - */ -function isWritable(obj, key) { - var descriptor = Object.getOwnPropertyDescriptor(obj, key); - return isUndefined(obj[key]) || descriptor && descriptor.writable -} - -/** - * Check if passed argument is a reserved name - * @param { String } value - - * @returns { Boolean } - - */ -function isReservedName(value) { - return RE_RESERVED_NAMES.test(value) -} - -var check = Object.freeze({ - isBoolAttr: isBoolAttr, - isFunction: isFunction, - isObject: isObject, - isUndefined: isUndefined, - isString: isString, - isBlank: isBlank, - isArray: isArray, - isWritable: isWritable, - isReservedName: isReservedName -}); - -/** - * Shorter and fast way to select multiple nodes in the DOM - * @param { String } selector - DOM selector - * @param { Object } ctx - DOM node where the targets of our search will is located - * @returns { Object } dom nodes found - */ -function $$(selector, ctx) { - return Array.prototype.slice.call((ctx || document).querySelectorAll(selector)) -} - -/** - * Shorter and fast way to select a single node in the DOM - * @param { String } selector - unique dom selector - * @param { Object } ctx - DOM node where the target of our search will is located - * @returns { Object } dom node found - */ -function $(selector, ctx) { - return (ctx || document).querySelector(selector) -} - -/** - * Create a document fragment - * @returns { Object } document fragment - */ -function createFrag() { - return document.createDocumentFragment() -} - -/** - * Create a document text node - * @returns { Object } create a text node to use as placeholder - */ -function createDOMPlaceholder() { - return document.createTextNode('') -} - -/** - * Check if a DOM node is an svg tag - * @param { HTMLElement } el - node we want to test - * @returns {Boolean} true if it's an svg node - */ -function isSvg(el) { - return !!el.ownerSVGElement -} - -/** - * Create a generic DOM node - * @param { String } name - name of the DOM node we want to create - * @param { Boolean } isSvg - true if we need to use an svg node - * @returns { Object } DOM node just created - */ -function mkEl(name) { - return name === 'svg' ? document.createElementNS(SVG_NS, name) : document.createElement(name) -} - -/** - * Set the inner html of any DOM node SVGs included - * @param { Object } container - DOM node where we'll inject new html - * @param { String } html - html to inject - */ -/* istanbul ignore next */ -function setInnerHTML(container, html) { - if (!isUndefined(container.innerHTML)) - { container.innerHTML = html; } - // some browsers do not support innerHTML on the SVGs tags - else { - var doc = new DOMParser().parseFromString(html, 'application/xml'); - var node = container.ownerDocument.importNode(doc.documentElement, true); - container.appendChild(node); - } -} - -/** - * Toggle the visibility of any DOM node - * @param { Object } dom - DOM node we want to hide - * @param { Boolean } show - do we want to show it? - */ - -function toggleVisibility(dom, show) { - dom.style.display = show ? '' : 'none'; - dom['hidden'] = show ? false : true; -} - -/** - * Remove any DOM attribute from a node - * @param { Object } dom - DOM node we want to update - * @param { String } name - name of the property we want to remove - */ -function remAttr(dom, name) { - dom.removeAttribute(name); -} - -/** - * Convert a style object to a string - * @param { Object } style - style object we need to parse - * @returns { String } resulting css string - * @example - * styleObjectToString({ color: 'red', height: '10px'}) // => 'color: red; height: 10px' - */ -function styleObjectToString(style) { - return Object.keys(style).reduce(function (acc, prop) { - return (acc + " " + prop + ": " + (style[prop]) + ";") - }, '') -} - -/** - * Get the value of any DOM attribute on a node - * @param { Object } dom - DOM node we want to parse - * @param { String } name - name of the attribute we want to get - * @returns { String | undefined } name of the node attribute whether it exists - */ -function getAttr(dom, name) { - return dom.getAttribute(name) -} - -/** - * Set any DOM attribute - * @param { Object } dom - DOM node we want to update - * @param { String } name - name of the property we want to set - * @param { String } val - value of the property we want to set - */ -function setAttr(dom, name, val) { - var xlink = XLINK_REGEX.exec(name); - if (xlink && xlink[1]) - { dom.setAttributeNS(XLINK_NS, xlink[1], val); } - else - { dom.setAttribute(name, val); } -} - -/** - * Insert safely a tag to fix #1962 #1649 - * @param { HTMLElement } root - children container - * @param { HTMLElement } curr - node to insert - * @param { HTMLElement } next - node that should preceed the current node inserted - */ -function safeInsert(root, curr, next) { - root.insertBefore(curr, next.parentNode && next); -} - -/** - * Minimize risk: only zero or one _space_ between attr & value - * @param { String } html - html string we want to parse - * @param { Function } fn - callback function to apply on any attribute found - */ -function walkAttrs(html, fn) { - if (!html) - { return } - var m; - while (m = RE_HTML_ATTRS.exec(html)) - { fn(m[1].toLowerCase(), m[2] || m[3] || m[4]); } -} - -/** - * Walk down recursively all the children tags starting dom node - * @param { Object } dom - starting node where we will start the recursion - * @param { Function } fn - callback to transform the child node just found - * @param { Object } context - fn can optionally return an object, which is passed to children - */ -function walkNodes(dom, fn, context) { - if (dom) { - var res = fn(dom, context); - var next; - // stop the recursion - if (res === false) { return } - - dom = dom.firstChild; - - while (dom) { - next = dom.nextSibling; - walkNodes(dom, fn, res); - dom = next; - } - } -} - -var dom = Object.freeze({ - $$: $$, - $: $, - createFrag: createFrag, - createDOMPlaceholder: createDOMPlaceholder, - isSvg: isSvg, - mkEl: mkEl, - setInnerHTML: setInnerHTML, - toggleVisibility: toggleVisibility, - remAttr: remAttr, - styleObjectToString: styleObjectToString, - getAttr: getAttr, - setAttr: setAttr, - safeInsert: safeInsert, - walkAttrs: walkAttrs, - walkNodes: walkNodes -}); - -var styleNode; -var cssTextProp; -var byName = {}; -var remainder = []; -var needsInject = false; - -// skip the following code on the server -if (WIN) { - styleNode = (function () { - // create a new style element with the correct type - var newNode = mkEl('style'); - setAttr(newNode, 'type', 'text/css'); - - // replace any user node or insert the new one into the head - var userNode = $('style[type=riot]'); - /* istanbul ignore next */ - if (userNode) { - if (userNode.id) { newNode.id = userNode.id; } - userNode.parentNode.replaceChild(newNode, userNode); - } - else { document.getElementsByTagName('head')[0].appendChild(newNode); } - - return newNode - })(); - cssTextProp = styleNode.styleSheet; -} - -/** - * Object that will be used to inject and manage the css of every tag instance - */ -var styleManager = { - styleNode: styleNode, - /** - * Save a tag style to be later injected into DOM - * @param { String } css - css string - * @param { String } name - if it's passed we will map the css to a tagname - */ - add: function add(css, name) { - if (name) { byName[name] = css; } - else { remainder.push(css); } - needsInject = true; - }, - /** - * Inject all previously saved tag styles into DOM - * innerHTML seems slow: http://jsperf.com/riot-insert-style - */ - inject: function inject() { - if (!WIN || !needsInject) { return } - needsInject = false; - var style = Object.keys(byName) - .map(function(k) { return byName[k] }) - .concat(remainder).join('\n'); - /* istanbul ignore next */ - if (cssTextProp) { cssTextProp.cssText = style; } - else { styleNode.innerHTML = style; } - } -}; - -/** - * The riot template engine - * @version v3.0.8 - */ - -var skipRegex = (function () { //eslint-disable-line no-unused-vars - - var beforeReChars = '[{(,;:?=|&!^~>%*/'; - - var beforeReWords = [ - 'case', - 'default', - 'do', - 'else', - 'in', - 'instanceof', - 'prefix', - 'return', - 'typeof', - 'void', - 'yield' - ]; - - var wordsLastChar = beforeReWords.reduce(function (s, w) { - return s + w.slice(-1) - }, ''); - - var RE_REGEX = /^\/(?=[^*>/])[^[/\\]*(?:(?:\\.|\[(?:\\.|[^\]\\]*)*\])[^[\\/]*)*?\/[gimuy]*/; - var RE_VN_CHAR = /[$\w]/; - - function prev (code, pos) { - while (--pos >= 0 && /\s/.test(code[pos])){ } - return pos - } - - function _skipRegex (code, start) { - - var re = /.*/g; - var pos = re.lastIndex = start++; - var match = re.exec(code)[0].match(RE_REGEX); - - if (match) { - var next = pos + match[0].length; - - pos = prev(code, pos); - var c = code[pos]; - - if (pos < 0 || ~beforeReChars.indexOf(c)) { - return next - } - - if (c === '.') { - - if (code[pos - 1] === '.') { - start = next; - } - - } else if (c === '+' || c === '-') { - - if (code[--pos] !== c || - (pos = prev(code, pos)) < 0 || - !RE_VN_CHAR.test(code[pos])) { - start = next; - } - - } else if (~wordsLastChar.indexOf(c)) { - - var end = pos + 1; - - while (--pos >= 0 && RE_VN_CHAR.test(code[pos])){ } - if (~beforeReWords.indexOf(code.slice(pos + 1, end))) { - start = next; - } - } - } - - return start - } - - return _skipRegex - -})(); - -/** - * riot.util.brackets - * - * - `brackets ` - Returns a string or regex based on its parameter - * - `brackets.set` - Change the current riot brackets - * - * @module - */ - -/* global riot */ - -var brackets = (function (UNDEF) { - - var - REGLOB = 'g', - - R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g, - - R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|`[^`\\]*(?:\\[\S\s][^`\\]*)*`/g, - - S_QBLOCKS = R_STRINGS.source + '|' + - /(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' + - /\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?([^<]\/)[gim]*/.source, - - UNSUPPORTED = RegExp('[\\' + 'x00-\\x1F<>a-zA-Z0-9\'",;\\\\]'), - - NEED_ESCAPE = /(?=[[\]()*+?.^$|])/g, - - S_QBLOCK2 = R_STRINGS.source + '|' + /(\/)(?![*\/])/.source, - - FINDBRACES = { - '(': RegExp('([()])|' + S_QBLOCK2, REGLOB), - '[': RegExp('([[\\]])|' + S_QBLOCK2, REGLOB), - '{': RegExp('([{}])|' + S_QBLOCK2, REGLOB) - }, - - DEFAULT = '{ }'; - - var _pairs = [ - '{', '}', - '{', '}', - /{[^}]*}/, - /\\([{}])/g, - /\\({)|{/g, - RegExp('\\\\(})|([[({])|(})|' + S_QBLOCK2, REGLOB), - DEFAULT, - /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/, - /(^|[^\\]){=[\S\s]*?}/ - ]; - - var - cachedBrackets = UNDEF, - _regex, - _cache = [], - _settings; - - function _loopback (re) { return re } - - function _rewrite (re, bp) { - if (!bp) { bp = _cache; } - return new RegExp( - re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' - ) - } - - function _create (pair) { - if (pair === DEFAULT) { return _pairs } - - var arr = pair.split(' '); - - if (arr.length !== 2 || UNSUPPORTED.test(pair)) { - throw new Error('Unsupported brackets "' + pair + '"') - } - arr = arr.concat(pair.replace(NEED_ESCAPE, '\\').split(' ')); - - arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr); - arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr); - arr[6] = _rewrite(_pairs[6], arr); - arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCK2, REGLOB); - arr[8] = pair; - return arr - } - - function _brackets (reOrIdx) { - return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx] - } - - _brackets.split = function split (str, tmpl, _bp) { - // istanbul ignore next: _bp is for the compiler - if (!_bp) { _bp = _cache; } - - var - parts = [], - match, - isexpr, - start, - pos, - re = _bp[6]; - - var qblocks = []; - var prevStr = ''; - var mark, lastIndex; - - isexpr = start = re.lastIndex = 0; - - while ((match = re.exec(str))) { - - lastIndex = re.lastIndex; - pos = match.index; - - if (isexpr) { - - if (match[2]) { - - var ch = match[2]; - var rech = FINDBRACES[ch]; - var ix = 1; - - rech.lastIndex = lastIndex; - while ((match = rech.exec(str))) { - if (match[1]) { - if (match[1] === ch) { ++ix; } - else if (!--ix) { break } - } else { - rech.lastIndex = pushQBlock(match.index, rech.lastIndex, match[2]); - } - } - re.lastIndex = ix ? str.length : rech.lastIndex; - continue - } - - if (!match[3]) { - re.lastIndex = pushQBlock(pos, lastIndex, match[4]); - continue - } - } - - if (!match[1]) { - unescapeStr(str.slice(start, pos)); - start = re.lastIndex; - re = _bp[6 + (isexpr ^= 1)]; - re.lastIndex = start; - } - } - - if (str && start < str.length) { - unescapeStr(str.slice(start)); - } - - parts.qblocks = qblocks; - - return parts - - function unescapeStr (s) { - if (prevStr) { - s = prevStr + s; - prevStr = ''; - } - if (tmpl || isexpr) { - parts.push(s && s.replace(_bp[5], '$1')); - } else { - parts.push(s); - } - } - - function pushQBlock(_pos, _lastIndex, slash) { //eslint-disable-line - if (slash) { - _lastIndex = skipRegex(str, _pos); - } - - if (tmpl && _lastIndex > _pos + 2) { - mark = '\u2057' + qblocks.length + '~'; - qblocks.push(str.slice(_pos, _lastIndex)); - prevStr += str.slice(start, _pos) + mark; - start = _lastIndex; - } - return _lastIndex - } - }; - - _brackets.hasExpr = function hasExpr (str) { - return _cache[4].test(str) - }; - - _brackets.loopKeys = function loopKeys (expr) { - var m = expr.match(_cache[9]); - - return m - ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] } - : { val: expr.trim() } - }; - - _brackets.array = function array (pair) { - return pair ? _create(pair) : _cache - }; - - function _reset (pair) { - if ((pair || (pair = DEFAULT)) !== _cache[8]) { - _cache = _create(pair); - _regex = pair === DEFAULT ? _loopback : _rewrite; - _cache[9] = _regex(_pairs[9]); - } - cachedBrackets = pair; - } - - function _setSettings (o) { - var b; - - o = o || {}; - b = o.brackets; - Object.defineProperty(o, 'brackets', { - set: _reset, - get: function () { return cachedBrackets }, - enumerable: true - }); - _settings = o; - _reset(b); - } - - Object.defineProperty(_brackets, 'settings', { - set: _setSettings, - get: function () { return _settings } - }); - - /* istanbul ignore next: in the browser riot is always in the scope */ - _brackets.settings = typeof riot !== 'undefined' && riot.settings || {}; - _brackets.set = _reset; - _brackets.skipRegex = skipRegex; - - _brackets.R_STRINGS = R_STRINGS; - _brackets.R_MLCOMMS = R_MLCOMMS; - _brackets.S_QBLOCKS = S_QBLOCKS; - _brackets.S_QBLOCK2 = S_QBLOCK2; - - return _brackets - -})(); - -/** - * @module tmpl - * - * tmpl - Root function, returns the template value, render with data - * tmpl.hasExpr - Test the existence of a expression inside a string - * tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`) - */ - -var tmpl = (function () { - - var _cache = {}; - - function _tmpl (str, data) { - if (!str) { return str } - - return (_cache[str] || (_cache[str] = _create(str))).call( - data, _logErr.bind({ - data: data, - tmpl: str - }) - ) - } - - _tmpl.hasExpr = brackets.hasExpr; - - _tmpl.loopKeys = brackets.loopKeys; - - // istanbul ignore next - _tmpl.clearCache = function () { _cache = {}; }; - - _tmpl.errorHandler = null; - - function _logErr (err, ctx) { - - err.riotData = { - tagName: ctx && ctx.__ && ctx.__.tagName, - _riot_id: ctx && ctx._riot_id //eslint-disable-line camelcase - }; - - if (_tmpl.errorHandler) { _tmpl.errorHandler(err); } - else if ( - typeof console !== 'undefined' && - typeof console.error === 'function' - ) { - console.error(err.message); - console.log('<%s> %s', err.riotData.tagName || 'Unknown tag', this.tmpl); // eslint-disable-line - console.log(this.data); // eslint-disable-line - } - } - - function _create (str) { - var expr = _getTmpl(str); - - if (expr.slice(0, 11) !== 'try{return ') { expr = 'return ' + expr; } - - return new Function('E', expr + ';') // eslint-disable-line no-new-func - } - - var RE_DQUOTE = /\u2057/g; - var RE_QBMARK = /\u2057(\d+)~/g; - - function _getTmpl (str) { - var parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1); - var qstr = parts.qblocks; - var expr; - - if (parts.length > 2 || parts[0]) { - var i, j, list = []; - - for (i = j = 0; i < parts.length; ++i) { - - expr = parts[i]; - - if (expr && (expr = i & 1 - - ? _parseExpr(expr, 1, qstr) - - : '"' + expr - .replace(/\\/g, '\\\\') - .replace(/\r\n?|\n/g, '\\n') - .replace(/"/g, '\\"') + - '"' - - )) { list[j++] = expr; } - - } - - expr = j < 2 ? list[0] - : '[' + list.join(',') + '].join("")'; - - } else { - - expr = _parseExpr(parts[1], 0, qstr); - } - - if (qstr.length) { - expr = expr.replace(RE_QBMARK, function (_, pos) { - return qstr[pos] - .replace(/\r/g, '\\r') - .replace(/\n/g, '\\n') - }); - } - return expr - } - - var RE_CSNAME = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/; - var - RE_BREND = { - '(': /[()]/g, - '[': /[[\]]/g, - '{': /[{}]/g - }; - - function _parseExpr (expr, asText, qstr) { - - expr = expr - .replace(/\s+/g, ' ').trim() - .replace(/\ ?([[\({},?\.:])\ ?/g, '$1'); - - if (expr) { - var - list = [], - cnt = 0, - match; - - while (expr && - (match = expr.match(RE_CSNAME)) && - !match.index - ) { - var - key, - jsb, - re = /,|([[{(])|$/g; - - expr = RegExp.rightContext; - key = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1]; - - while (jsb = (match = re.exec(expr))[1]) { skipBraces(jsb, re); } - - jsb = expr.slice(0, match.index); - expr = RegExp.rightContext; - - list[cnt++] = _wrapExpr(jsb, 1, key); - } - - expr = !cnt ? _wrapExpr(expr, asText) - : cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0]; - } - return expr - - function skipBraces (ch, re) { - var - mm, - lv = 1, - ir = RE_BREND[ch]; - - ir.lastIndex = re.lastIndex; - while (mm = ir.exec(expr)) { - if (mm[0] === ch) { ++lv; } - else if (!--lv) { break } - } - re.lastIndex = lv ? expr.length : ir.lastIndex; - } - } - - // istanbul ignore next: not both - var // eslint-disable-next-line max-len - JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').', - JS_VARNAME = /[,{][\$\w]+(?=:)|(^ *|[^$\w\.{])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g, - JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/; - - function _wrapExpr (expr, asText, key) { - var tb; - - expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) { - if (mvar) { - pos = tb ? 0 : pos + match.length; - - if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') { - match = p + '("' + mvar + JS_CONTEXT + mvar; - if (pos) { tb = (s = s[pos]) === '.' || s === '(' || s === '['; } - } else if (pos) { - tb = !JS_NOPROPS.test(s.slice(pos)); - } - } - return match - }); - - if (tb) { - expr = 'try{return ' + expr + '}catch(e){E(e,this)}'; - } - - if (key) { - - expr = (tb - ? 'function(){' + expr + '}.call(this)' : '(' + expr + ')' - ) + '?"' + key + '":""'; - - } else if (asText) { - - expr = 'function(v){' + (tb - ? expr.replace('return ', 'v=') : 'v=(' + expr + ')' - ) + ';return v||v===0?v:""}.call(this)'; - } - - return expr - } - - _tmpl.version = brackets.version = 'v3.0.8'; - - return _tmpl - -})(); - -var observable$1 = function(el) { - - /** - * Extend the original object or create a new empty one - * @type { Object } - */ - - el = el || {}; - - /** - * Private variables - */ - var callbacks = {}, - slice = Array.prototype.slice; - - /** - * Public Api - */ - - // extend the el object adding the observable methods - Object.defineProperties(el, { - /** - * Listen to the given `event` ands - * execute the `callback` each time an event is triggered. - * @param { String } event - event id - * @param { Function } fn - callback function - * @returns { Object } el - */ - on: { - value: function(event, fn) { - if (typeof fn == 'function') - { (callbacks[event] = callbacks[event] || []).push(fn); } - return el - }, - enumerable: false, - writable: false, - configurable: false - }, - - /** - * Removes the given `event` listeners - * @param { String } event - event id - * @param { Function } fn - callback function - * @returns { Object } el - */ - off: { - value: function(event, fn) { - if (event == '*' && !fn) { callbacks = {}; } - else { - if (fn) { - var arr = callbacks[event]; - for (var i = 0, cb; cb = arr && arr[i]; ++i) { - if (cb == fn) { arr.splice(i--, 1); } - } - } else { delete callbacks[event]; } - } - return el - }, - enumerable: false, - writable: false, - configurable: false - }, - - /** - * Listen to the given `event` and - * execute the `callback` at most once - * @param { String } event - event id - * @param { Function } fn - callback function - * @returns { Object } el - */ - one: { - value: function(event, fn) { - function on() { - el.off(event, on); - fn.apply(el, arguments); - } - return el.on(event, on) - }, - enumerable: false, - writable: false, - configurable: false - }, - - /** - * Execute all callback functions that listen to - * the given `event` - * @param { String } event - event id - * @returns { Object } el - */ - trigger: { - value: function(event) { - var arguments$1 = arguments; - - - // getting the arguments - var arglen = arguments.length - 1, - args = new Array(arglen), - fns, - fn, - i; - - for (i = 0; i < arglen; i++) { - args[i] = arguments$1[i + 1]; // skip first argument - } - - fns = slice.call(callbacks[event] || [], 0); - - for (i = 0; fn = fns[i]; ++i) { - fn.apply(el, args); - } - - if (callbacks['*'] && event != '*') - { el.trigger.apply(el, ['*', event].concat(args)); } - - return el - }, - enumerable: false, - writable: false, - configurable: false - } - }); - - return el - -}; - -/** - * Specialized function for looping an array-like collection with `each={}` - * @param { Array } list - collection of items - * @param {Function} fn - callback function - * @returns { Array } the array looped - */ -function each(list, fn) { - var len = list ? list.length : 0; - var i = 0; - for (; i < len; ++i) { - fn(list[i], i); - } - return list -} - -/** - * Check whether an array contains an item - * @param { Array } array - target array - * @param { * } item - item to test - * @returns { Boolean } - - */ -function contains(array, item) { - return array.indexOf(item) !== -1 -} - -/** - * Convert a string containing dashes to camel case - * @param { String } str - input string - * @returns { String } my-string -> myString - */ -function toCamel(str) { - return str.replace(/-(\w)/g, function (_, c) { return c.toUpperCase(); }) -} - -/** - * Faster String startsWith alternative - * @param { String } str - source string - * @param { String } value - test string - * @returns { Boolean } - - */ -function startsWith(str, value) { - return str.slice(0, value.length) === value -} - -/** - * Helper function to set an immutable property - * @param { Object } el - object where the new property will be set - * @param { String } key - object key where the new property will be stored - * @param { * } value - value of the new property - * @param { Object } options - set the propery overriding the default options - * @returns { Object } - the initial object - */ -function defineProperty(el, key, value, options) { - Object.defineProperty(el, key, extend({ - value: value, - enumerable: false, - writable: false, - configurable: true - }, options)); - return el -} - -/** - * Extend any object with other properties - * @param { Object } src - source object - * @returns { Object } the resulting extended object - * - * var obj = { foo: 'baz' } - * extend(obj, {bar: 'bar', foo: 'bar'}) - * console.log(obj) => {bar: 'bar', foo: 'bar'} - * - */ -function extend(src) { - var obj, args = arguments; - for (var i = 1; i < args.length; ++i) { - if (obj = args[i]) { - for (var key in obj) { - // check if this property of the source object could be overridden - if (isWritable(src, key)) - { src[key] = obj[key]; } - } - } - } - return src -} - -var misc = Object.freeze({ - each: each, - contains: contains, - toCamel: toCamel, - startsWith: startsWith, - defineProperty: defineProperty, - extend: extend -}); - -var settings$1 = extend(Object.create(brackets.settings), { - skipAnonymousTags: true, - // handle the auto updates on any DOM event - autoUpdate: true -}); - -/** - * Trigger DOM events - * @param { HTMLElement } dom - dom element target of the event - * @param { Function } handler - user function - * @param { Object } e - event object - */ -function handleEvent(dom, handler, e) { - var ptag = this.__.parent, - item = this.__.item; - - if (!item) - { while (ptag && !item) { - item = ptag.__.item; - ptag = ptag.__.parent; - } } - - // override the event properties - /* istanbul ignore next */ - if (isWritable(e, 'currentTarget')) { e.currentTarget = dom; } - /* istanbul ignore next */ - if (isWritable(e, 'target')) { e.target = e.srcElement; } - /* istanbul ignore next */ - if (isWritable(e, 'which')) { e.which = e.charCode || e.keyCode; } - - e.item = item; - - handler.call(this, e); - - // avoid auto updates - if (!settings$1.autoUpdate) { return } - - if (!e.preventUpdate) { - var p = getImmediateCustomParentTag(this); - // fixes #2083 - if (p.isMounted) { p.update(); } - } -} - -/** - * Attach an event to a DOM node - * @param { String } name - event name - * @param { Function } handler - event callback - * @param { Object } dom - dom node - * @param { Tag } tag - tag instance - */ -function setEventHandler(name, handler, dom, tag) { - var eventName, - cb = handleEvent.bind(tag, dom, handler); - - // avoid to bind twice the same event - // possible fix for #2332 - dom[name] = null; - - // normalize event name - eventName = name.replace(RE_EVENTS_PREFIX, ''); - - // cache the listener into the listeners array - if (!contains(tag.__.listeners, dom)) { tag.__.listeners.push(dom); } - if (!dom[RIOT_EVENTS_KEY]) { dom[RIOT_EVENTS_KEY] = {}; } - if (dom[RIOT_EVENTS_KEY][name]) { dom.removeEventListener(eventName, dom[RIOT_EVENTS_KEY][name]); } - - dom[RIOT_EVENTS_KEY][name] = cb; - dom.addEventListener(eventName, cb, false); -} - -/** - * Update dynamically created data-is tags with changing expressions - * @param { Object } expr - expression tag and expression info - * @param { Tag } parent - parent for tag creation - * @param { String } tagName - tag implementation we want to use - */ -function updateDataIs(expr, parent, tagName) { - var conf, isVirtual, head, ref; - - if (expr.tag && expr.tagName === tagName) { - expr.tag.update(); - return - } - - isVirtual = expr.dom.tagName === 'VIRTUAL'; - // sync _parent to accommodate changing tagnames - if (expr.tag) { - // need placeholder before unmount - if(isVirtual) { - head = expr.tag.__.head; - ref = createDOMPlaceholder(); - head.parentNode.insertBefore(ref, head); - } - - expr.tag.unmount(true); - } - - if (!isString(tagName)) { return } - - expr.impl = __TAG_IMPL[tagName]; - conf = {root: expr.dom, parent: parent, hasImpl: true, tagName: tagName}; - expr.tag = initChildTag(expr.impl, conf, expr.dom.innerHTML, parent); - each(expr.attrs, function (a) { return setAttr(expr.tag.root, a.name, a.value); }); - expr.tagName = tagName; - expr.tag.mount(); - if (isVirtual) - { makeReplaceVirtual(expr.tag, ref || expr.tag.root); } // root exist first time, after use placeholder - - // parent is the placeholder tag, not the dynamic tag so clean up - parent.__.onUnmount = function() { - var delName = expr.tag.opts.dataIs, - tags = expr.tag.parent.tags, - _tags = expr.tag.__.parent.tags; - arrayishRemove(tags, delName, expr.tag); - arrayishRemove(_tags, delName, expr.tag); - expr.tag.unmount(); - }; -} - -/** - * Nomalize any attribute removing the "riot-" prefix - * @param { String } attrName - original attribute name - * @returns { String } valid html attribute name - */ -function normalizeAttrName(attrName) { - if (!attrName) { return null } - attrName = attrName.replace(ATTRS_PREFIX, ''); - if (CASE_SENSITIVE_ATTRIBUTES[attrName]) { attrName = CASE_SENSITIVE_ATTRIBUTES[attrName]; } - return attrName -} - -/** - * Update on single tag expression - * @this Tag - * @param { Object } expr - expression logic - * @returns { undefined } - */ -function updateExpression(expr) { - if (this.root && getAttr(this.root,'virtualized')) { return } - - var dom = expr.dom, - // remove the riot- prefix - attrName = normalizeAttrName(expr.attr), - isToggle = contains([SHOW_DIRECTIVE, HIDE_DIRECTIVE], attrName), - isVirtual = expr.root && expr.root.tagName === 'VIRTUAL', - parent = dom && (expr.parent || dom.parentNode), - // detect the style attributes - isStyleAttr = attrName === 'style', - isClassAttr = attrName === 'class', - hasValue, - isObj, - value; - - // if it's a tag we could totally skip the rest - if (expr._riot_id) { - if (expr.isMounted) { - expr.update(); - // if it hasn't been mounted yet, do that now. - } else { - expr.mount(); - if (isVirtual) { - makeReplaceVirtual(expr, expr.root); - } - } - return - } - // if this expression has the update method it means it can handle the DOM changes by itself - if (expr.update) { return expr.update() } - - // ...it seems to be a simple expression so we try to calculat its value - value = tmpl(expr.expr, isToggle ? extend({}, Object.create(this.parent), this) : this); - hasValue = !isBlank(value); - isObj = isObject(value); - - // convert the style/class objects to strings - if (isObj) { - isObj = !isClassAttr && !isStyleAttr; - if (isClassAttr) { - value = tmpl(JSON.stringify(value), this); - } else if (isStyleAttr) { - value = styleObjectToString(value); - } - } - - // remove original attribute - if (expr.attr && (!expr.isAttrRemoved || !hasValue || value === false)) { - remAttr(dom, expr.attr); - expr.isAttrRemoved = true; - } - - // for the boolean attributes we don't need the value - // we can convert it to checked=true to checked=checked - if (expr.bool) { value = value ? attrName : false; } - if (expr.isRtag) { return updateDataIs(expr, this, value) } - if (expr.wasParsedOnce && expr.value === value) { return } - - // update the expression value - expr.value = value; - expr.wasParsedOnce = true; - - // if the value is an object we can not do much more with it - if (isObj && !isToggle) { return } - // avoid to render undefined/null values - if (isBlank(value)) { value = ''; } - - // textarea and text nodes have no attribute name - if (!attrName) { - // about #815 w/o replace: the browser converts the value to a string, - // the comparison by "==" does too, but not in the server - value += ''; - // test for parent avoids error with invalid assignment to nodeValue - if (parent) { - // cache the parent node because somehow it will become null on IE - // on the next iteration - expr.parent = parent; - if (parent.tagName === 'TEXTAREA') { - parent.value = value; // #1113 - if (!IE_VERSION) { dom.nodeValue = value; } // #1625 IE throws here, nodeValue - } // will be available on 'updated' - else { dom.nodeValue = value; } - } - return - } - - - // event handler - if (isFunction(value)) { - setEventHandler(attrName, value, dom, this); - // show / hide - } else if (isToggle) { - toggleVisibility(dom, attrName === HIDE_DIRECTIVE ? !value : value); - // handle attributes - } else { - if (expr.bool) { - dom[attrName] = value; - } - - if (attrName === 'value' && dom.value !== value) { - dom.value = value; - } - - if (hasValue && value !== false) { - setAttr(dom, attrName, value); - } - - // make sure that in case of style changes - // the element stays hidden - if (isStyleAttr && dom.hidden) { toggleVisibility(dom, false); } - } -} - -/** - * Update all the expressions in a Tag instance - * @this Tag - * @param { Array } expressions - expression that must be re evaluated - */ -function updateAllExpressions(expressions) { - each(expressions, updateExpression.bind(this)); -} - -var IfExpr = { - init: function init(dom, tag, expr) { - remAttr(dom, CONDITIONAL_DIRECTIVE); - this.tag = tag; - this.expr = expr; - this.stub = createDOMPlaceholder(); - this.pristine = dom; - - var p = dom.parentNode; - p.insertBefore(this.stub, dom); - p.removeChild(dom); - - return this - }, - update: function update() { - this.value = tmpl(this.expr, this.tag); - - if (this.value && !this.current) { // insert - this.current = this.pristine.cloneNode(true); - this.stub.parentNode.insertBefore(this.current, this.stub); - this.expressions = []; - parseExpressions.apply(this.tag, [this.current, this.expressions, true]); - } else if (!this.value && this.current) { // remove - unmountAll(this.expressions); - if (this.current._tag) { - this.current._tag.unmount(); - } else if (this.current.parentNode) { - this.current.parentNode.removeChild(this.current); - } - this.current = null; - this.expressions = []; - } - - if (this.value) { updateAllExpressions.call(this.tag, this.expressions); } - }, - unmount: function unmount() { - unmountAll(this.expressions || []); - } -}; - -var RefExpr = { - init: function init(dom, parent, attrName, attrValue) { - this.dom = dom; - this.attr = attrName; - this.rawValue = attrValue; - this.parent = parent; - this.hasExp = tmpl.hasExpr(attrValue); - return this - }, - update: function update() { - var old = this.value; - var customParent = this.parent && getImmediateCustomParentTag(this.parent); - // if the referenced element is a custom tag, then we set the tag itself, rather than DOM - var tagOrDom = this.dom.__ref || this.tag || this.dom; - - this.value = this.hasExp ? tmpl(this.rawValue, this.parent) : this.rawValue; - - // the name changed, so we need to remove it from the old key (if present) - if (!isBlank(old) && customParent) { arrayishRemove(customParent.refs, old, tagOrDom); } - if (!isBlank(this.value) && isString(this.value)) { - // add it to the refs of parent tag (this behavior was changed >=3.0) - if (customParent) { arrayishAdd( - customParent.refs, - this.value, - tagOrDom, - // use an array if it's a looped node and the ref is not an expression - null, - this.parent.__.index - ); } - - if (this.value !== old) { - setAttr(this.dom, this.attr, this.value); - } - } else { - remAttr(this.dom, this.attr); - } - - // cache the ref bound to this dom node - // to reuse it in future (see also #2329) - if (!this.dom.__ref) { this.dom.__ref = tagOrDom; } - }, - unmount: function unmount() { - var tagOrDom = this.tag || this.dom; - var customParent = this.parent && getImmediateCustomParentTag(this.parent); - if (!isBlank(this.value) && customParent) - { arrayishRemove(customParent.refs, this.value, tagOrDom); } - } -}; - -/** - * Convert the item looped into an object used to extend the child tag properties - * @param { Object } expr - object containing the keys used to extend the children tags - * @param { * } key - value to assign to the new object returned - * @param { * } val - value containing the position of the item in the array - * @param { Object } base - prototype object for the new item - * @returns { Object } - new object containing the values of the original item - * - * The variables 'key' and 'val' are arbitrary. - * They depend on the collection type looped (Array, Object) - * and on the expression used on the each tag - * - */ -function mkitem(expr, key, val, base) { - var item = base ? Object.create(base) : {}; - item[expr.key] = key; - if (expr.pos) { item[expr.pos] = val; } - return item -} - -/** - * Unmount the redundant tags - * @param { Array } items - array containing the current items to loop - * @param { Array } tags - array containing all the children tags - */ -function unmountRedundant(items, tags) { - var i = tags.length, - j = items.length; - - while (i > j) { - i--; - remove.apply(tags[i], [tags, i]); - } -} - - -/** - * Remove a child tag - * @this Tag - * @param { Array } tags - tags collection - * @param { Number } i - index of the tag to remove - */ -function remove(tags, i) { - tags.splice(i, 1); - this.unmount(); - arrayishRemove(this.parent, this, this.__.tagName, true); -} - -/** - * Move the nested custom tags in non custom loop tags - * @this Tag - * @param { Number } i - current position of the loop tag - */ -function moveNestedTags(i) { - var this$1 = this; - - each(Object.keys(this.tags), function (tagName) { - moveChildTag.apply(this$1.tags[tagName], [tagName, i]); - }); -} - -/** - * Move a child tag - * @this Tag - * @param { HTMLElement } root - dom node containing all the loop children - * @param { Tag } nextTag - instance of the next tag preceding the one we want to move - * @param { Boolean } isVirtual - is it a virtual tag? - */ -function move(root, nextTag, isVirtual) { - if (isVirtual) - { moveVirtual.apply(this, [root, nextTag]); } - else - { safeInsert(root, this.root, nextTag.root); } -} - -/** - * Insert and mount a child tag - * @this Tag - * @param { HTMLElement } root - dom node containing all the loop children - * @param { Tag } nextTag - instance of the next tag preceding the one we want to insert - * @param { Boolean } isVirtual - is it a virtual tag? - */ -function insert(root, nextTag, isVirtual) { - if (isVirtual) - { makeVirtual.apply(this, [root, nextTag]); } - else - { safeInsert(root, this.root, nextTag.root); } -} - -/** - * Append a new tag into the DOM - * @this Tag - * @param { HTMLElement } root - dom node containing all the loop children - * @param { Boolean } isVirtual - is it a virtual tag? - */ -function append(root, isVirtual) { - if (isVirtual) - { makeVirtual.call(this, root); } - else - { root.appendChild(this.root); } -} - -/** - * Manage tags having the 'each' - * @param { HTMLElement } dom - DOM node we need to loop - * @param { Tag } parent - parent tag instance where the dom node is contained - * @param { String } expr - string contained in the 'each' attribute - * @returns { Object } expression object for this each loop - */ -function _each(dom, parent, expr) { - - // remove the each property from the original tag - remAttr(dom, LOOP_DIRECTIVE); - - var mustReorder = typeof getAttr(dom, LOOP_NO_REORDER_DIRECTIVE) !== T_STRING || remAttr(dom, LOOP_NO_REORDER_DIRECTIVE), - tagName = getTagName(dom), - impl = __TAG_IMPL[tagName], - parentNode = dom.parentNode, - placeholder = createDOMPlaceholder(), - child = getTag(dom), - ifExpr = getAttr(dom, CONDITIONAL_DIRECTIVE), - tags = [], - oldItems = [], - hasKeys, - isLoop = true, - isAnonymous = !__TAG_IMPL[tagName], - isVirtual = dom.tagName === 'VIRTUAL'; - - // parse the each expression - expr = tmpl.loopKeys(expr); - expr.isLoop = true; - - if (ifExpr) { remAttr(dom, CONDITIONAL_DIRECTIVE); } - - // insert a marked where the loop tags will be injected - parentNode.insertBefore(placeholder, dom); - parentNode.removeChild(dom); - - expr.update = function updateEach() { - // get the new items collection - expr.value = tmpl(expr.val, parent); - - var frag = createFrag(), - items = expr.value, - isObject$$1 = !isArray(items) && !isString(items), - root = placeholder.parentNode; - - // if this DOM was removed the update here is useless - // this condition fixes also a weird async issue on IE in our unit test - if (!root) { return } - - // object loop. any changes cause full redraw - if (isObject$$1) { - hasKeys = items || false; - items = hasKeys ? - Object.keys(items).map(function (key) { - return mkitem(expr, items[key], key) - }) : []; - } else { - hasKeys = false; - } - - if (ifExpr) { - items = items.filter(function(item, i) { - if (expr.key && !isObject$$1) - { return !!tmpl(ifExpr, mkitem(expr, item, i, parent)) } - - return !!tmpl(ifExpr, extend(Object.create(parent), item)) - }); - } - - // loop all the new items - each(items, function(item, i) { - // reorder only if the items are objects - var - doReorder = mustReorder && typeof item === T_OBJECT && !hasKeys, - oldPos = oldItems.indexOf(item), - isNew = oldPos === -1, - pos = !isNew && doReorder ? oldPos : i, - // does a tag exist in this position? - tag = tags[pos], - mustAppend = i >= oldItems.length, - mustCreate = doReorder && isNew || !doReorder && !tag; - - item = !hasKeys && expr.key ? mkitem(expr, item, i) : item; - - // new tag - if (mustCreate) { - tag = new Tag$1(impl, { - parent: parent, - isLoop: isLoop, - isAnonymous: isAnonymous, - tagName: tagName, - root: dom.cloneNode(isAnonymous), - item: item, - index: i, - }, dom.innerHTML); - - // mount the tag - tag.mount(); - - if (mustAppend) - { append.apply(tag, [frag || root, isVirtual]); } - else - { insert.apply(tag, [root, tags[i], isVirtual]); } - - if (!mustAppend) { oldItems.splice(i, 0, item); } - tags.splice(i, 0, tag); - if (child) { arrayishAdd(parent.tags, tagName, tag, true); } - } else if (pos !== i && doReorder) { - // move - if (contains(items, oldItems[pos])) { - move.apply(tag, [root, tags[i], isVirtual]); - // move the old tag instance - tags.splice(i, 0, tags.splice(pos, 1)[0]); - // move the old item - oldItems.splice(i, 0, oldItems.splice(pos, 1)[0]); - } - - // update the position attribute if it exists - if (expr.pos) { tag[expr.pos] = i; } - - // if the loop tags are not custom - // we need to move all their custom tags into the right position - if (!child && tag.tags) { moveNestedTags.call(tag, i); } - } - - // cache the original item to use it in the events bound to this node - // and its children - tag.__.item = item; - tag.__.index = i; - tag.__.parent = parent; - - if (!mustCreate) { tag.update(item); } - }); - - // remove the redundant tags - unmountRedundant(items, tags); - - // clone the items array - oldItems = items.slice(); - - // this condition is weird u - root.insertBefore(frag, placeholder); - }; - - expr.unmount = function() { - each(tags, function(t) { t.unmount(); }); - }; - - return expr -} - -/** - * Walk the tag DOM to detect the expressions to evaluate - * @this Tag - * @param { HTMLElement } root - root tag where we will start digging the expressions - * @param { Array } expressions - empty array where the expressions will be added - * @param { Boolean } mustIncludeRoot - flag to decide whether the root must be parsed as well - * @returns { Object } an object containing the root noode and the dom tree - */ -function parseExpressions(root, expressions, mustIncludeRoot) { - var this$1 = this; - - var tree = {parent: {children: expressions}}; - - walkNodes(root, function (dom, ctx) { - var type = dom.nodeType, parent = ctx.parent, attr, expr, tagImpl; - if (!mustIncludeRoot && dom === root) { return {parent: parent} } - - // text node - if (type === 3 && dom.parentNode.tagName !== 'STYLE' && tmpl.hasExpr(dom.nodeValue)) - { parent.children.push({dom: dom, expr: dom.nodeValue}); } - - if (type !== 1) { return ctx } // not an element - - var isVirtual = dom.tagName === 'VIRTUAL'; - - // loop. each does it's own thing (for now) - if (attr = getAttr(dom, LOOP_DIRECTIVE)) { - if(isVirtual) { setAttr(dom, 'loopVirtual', true); } // ignore here, handled in _each - parent.children.push(_each(dom, this$1, attr)); - return false - } - - // if-attrs become the new parent. Any following expressions (either on the current - // element, or below it) become children of this expression. - if (attr = getAttr(dom, CONDITIONAL_DIRECTIVE)) { - parent.children.push(Object.create(IfExpr).init(dom, this$1, attr)); - return false - } - - if (expr = getAttr(dom, IS_DIRECTIVE)) { - if (tmpl.hasExpr(expr)) { - parent.children.push({isRtag: true, expr: expr, dom: dom, attrs: [].slice.call(dom.attributes)}); - return false - } - } - - // if this is a tag, stop traversing here. - // we ignore the root, since parseExpressions is called while we're mounting that root - tagImpl = getTag(dom); - if(isVirtual) { - if(getAttr(dom, 'virtualized')) {dom.parentElement.removeChild(dom); } // tag created, remove from dom - if(!tagImpl && !getAttr(dom, 'virtualized') && !getAttr(dom, 'loopVirtual')) // ok to create virtual tag - { tagImpl = { tmpl: dom.outerHTML }; } - } - - if (tagImpl && (dom !== root || mustIncludeRoot)) { - if(isVirtual && !getAttr(dom, IS_DIRECTIVE)) { // handled in update - // can not remove attribute like directives - // so flag for removal after creation to prevent maximum stack error - setAttr(dom, 'virtualized', true); - - var tag = new Tag$1({ tmpl: dom.outerHTML }, - {root: dom, parent: this$1}, - dom.innerHTML); - parent.children.push(tag); // no return, anonymous tag, keep parsing - } else { - var conf = {root: dom, parent: this$1, hasImpl: true}; - parent.children.push(initChildTag(tagImpl, conf, dom.innerHTML, this$1)); - return false - } - } - - // attribute expressions - parseAttributes.apply(this$1, [dom, dom.attributes, function(attr, expr) { - if (!expr) { return } - parent.children.push(expr); - }]); - - // whatever the parent is, all child elements get the same parent. - // If this element had an if-attr, that's the parent for all child elements - return {parent: parent} - }, tree); -} - -/** - * Calls `fn` for every attribute on an element. If that attr has an expression, - * it is also passed to fn. - * @this Tag - * @param { HTMLElement } dom - dom node to parse - * @param { Array } attrs - array of attributes - * @param { Function } fn - callback to exec on any iteration - */ -function parseAttributes(dom, attrs, fn) { - var this$1 = this; - - each(attrs, function (attr) { - if (!attr) { return false } - - var name = attr.name, bool = isBoolAttr(name), expr; - - if (contains(REF_DIRECTIVES, name)) { - expr = Object.create(RefExpr).init(dom, this$1, name, attr.value); - } else if (tmpl.hasExpr(attr.value)) { - expr = {dom: dom, expr: attr.value, attr: name, bool: bool}; - } - - fn(attr, expr); - }); -} - -/* - Includes hacks needed for the Internet Explorer version 9 and below - See: http://kangax.github.io/compat-table/es5/#ie8 - http://codeplanet.io/dropping-ie8/ -*/ - -var reHasYield = /|>([\S\s]*?)<\/yield\s*>|>)/ig; -var reYieldSrc = /]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig; -var reYieldDest = /|>([\S\s]*?)<\/yield\s*>)/ig; -var rootEls = { tr: 'tbody', th: 'tr', td: 'tr', col: 'colgroup' }; -var tblTags = IE_VERSION && IE_VERSION < 10 ? RE_SPECIAL_TAGS : RE_SPECIAL_TAGS_NO_OPTION; -var GENERIC = 'div'; -var SVG = 'svg'; - - -/* - Creates the root element for table or select child elements: - tr/th/td/thead/tfoot/tbody/caption/col/colgroup/option/optgroup -*/ -function specialTags(el, tmpl, tagName) { - - var - select = tagName[0] === 'o', - parent = select ? 'select>' : 'table>'; - - // trim() is important here, this ensures we don't have artifacts, - // so we can check if we have only one element inside the parent - el.innerHTML = '<' + parent + tmpl.trim() + '= 0 && length <= MAX_ARRAY_INDEX; - }; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles raw objects in addition to array-likes. Treats all - // sparse array-likes as if they were dense. - _.each = _.forEach = function(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); - } - } - return obj; - }; - - // Return the results of applying the iteratee to each element. - _.map = _.collect = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Create a reducing function iterating left or right. - function createReduce(dir) { - // Optimized iterator function as using arguments.length - // in the main function will deoptimize the, see #1991. - function iterator(obj, iteratee, memo, keys, index, length) { - for (; index >= 0 && index < length; index += dir) { - var currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - } - - return function(obj, iteratee, memo, context) { - iteratee = optimizeCb(iteratee, context, 4); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - index = dir > 0 ? 0 : length - 1; - // Determine the initial value if none is provided. - if (arguments.length < 3) { - memo = obj[keys ? keys[index] : index]; - index += dir; - } - return iterator(obj, iteratee, memo, keys, index, length); - }; - } - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. - _.reduce = _.foldl = _.inject = createReduce(1); - - // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = createReduce(-1); - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, predicate, context) { - var key; - if (isArrayLike(obj)) { - key = _.findIndex(obj, predicate, context); - } else { - key = _.findKey(obj, predicate, context); - } - if (key !== void 0 && key !== -1) { return obj[key]; } - }; - - // Return all the elements that pass a truth test. - // Aliased as `select`. - _.filter = _.select = function(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) { results.push(value); } - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(cb(predicate)), context); - }; - - // Determine whether all of the elements match a truth test. - // Aliased as `all`. - _.every = _.all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) { return false; } - } - return true; - }; - - // Determine if at least one element in the object matches a truth test. - // Aliased as `any`. - _.some = _.any = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) { return true; } - } - return false; - }; - - // Determine if the array or object contains a given item (using `===`). - // Aliased as `includes` and `include`. - _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) { obj = _.values(obj); } - if (typeof fromIndex != 'number' || guard) { fromIndex = 0; } - return _.indexOf(obj, item, fromIndex) >= 0; - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - var func = isFunc ? method : value[method]; - return func == null ? func : func.apply(value, args); - }); - }; - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs) { - return _.filter(obj, _.matcher(attrs)); - }; - - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matcher(attrs)); - }; - - // Return the maximum element (or element-based computation). - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value > result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value < result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Shuffle a collection, using the modern version of the - // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). - _.shuffle = function(obj) { - var set = isArrayLike(obj) ? obj : _.values(obj); - var length = set.length; - var shuffled = Array(length); - for (var index = 0, rand; index < length; index++) { - rand = _.random(0, index); - if (rand !== index) { shuffled[index] = shuffled[rand]; } - shuffled[rand] = set[index]; - } - return shuffled; - }; - - // Sample **n** random values from a collection. - // If **n** is not specified, returns a single random element. - // The internal `guard` argument allows it to work with `map`. - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) { obj = _.values(obj); } - return obj[_.random(obj.length - 1)]; - } - return _.shuffle(obj).slice(0, Math.max(0, n)); - }; - - // Sort the object's values by a criterion produced by an iteratee. - _.sortBy = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iteratee(value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) { return 1; } - if (a < b || b === void 0) { return -1; } - } - return left.index - right.index; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(behavior) { - return function(obj, iteratee, context) { - var result = {}; - iteratee = cb(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) { result[key].push(value); } else { result[key] = [value]; } - }); - - // Indexes the object's values by a criterion, similar to `groupBy`, but for - // when you know that your index values will be unique. - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) { result[key]++; } else { result[key] = 1; } - }); - - // Safely create a real, live array from anything iterable. - _.toArray = function(obj) { - if (!obj) { return []; } - if (_.isArray(obj)) { return slice.call(obj); } - if (isArrayLike(obj)) { return _.map(obj, _.identity); } - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) { return 0; } - return isArrayLike(obj) ? obj.length : _.keys(obj).length; - }; - - // Split a collection into two arrays: one whose elements all satisfy the given - // predicate, and one whose elements all do not satisfy the predicate. - _.partition = function(obj, predicate, context) { - predicate = cb(predicate, context); - var pass = [], fail = []; - _.each(obj, function(value, key, obj) { - (predicate(value, key, obj) ? pass : fail).push(value); - }); - return [pass, fail]; - }; - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) { return void 0; } - if (n == null || guard) { return array[0]; } - return _.initial(array, array.length - n); - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. - _.last = function(array, n, guard) { - if (array == null) { return void 0; } - if (n == null || guard) { return array[array.length - 1]; } - return _.rest(array, Math.max(0, array.length - n)); - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, _.identity); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, startIndex) { - var output = [], idx = 0; - for (var i = startIndex || 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { - //flatten current level of array or arguments object - if (!shallow) { value = flatten(value, shallow, strict); } - var j = 0, len = value.length; - output.length += len; - while (j < len) { - output[idx++] = value[j++]; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; - }; - - // Flatten out an array, either recursively (by default), or just one level. - _.flatten = function(array, shallow) { - return flatten(array, shallow, false); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) { iteratee = cb(iteratee, context); } - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], - computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted) { - if (!i || seen !== computed) { result.push(value); } - seen = computed; - } else if (iteratee) { - if (!_.contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!_.contains(result, value)) { - result.push(value); - } - } - return result; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(flatten(arguments, true, true)); - }; - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var arguments$1 = arguments; - - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) { continue; } - for (var j = 1; j < argsLength; j++) { - if (!_.contains(arguments$1[j], item)) { break; } - } - if (j === argsLength) { result.push(item); } - } - return result; - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = flatten(arguments, true, true, 1); - return _.filter(array, function(value){ - return !_.contains(rest, value); - }); - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function() { - return _.unzip(arguments); - }; - - // Complement of _.zip. Unzip accepts an array of arrays and groups - // each array's elements on shared indices - _.unzip = function(array) { - var length = array && _.max(array, getLength).length || 0; - var result = Array(length); - - for (var index = 0; index < length; index++) { - result[index] = _.pluck(array, index); - } - return result; - }; - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // Generator function to create the findIndex and findLastIndex functions - function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (; index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) { return index; } - } - return -1; - }; - } - - // Returns the first index on an array-like that passes a predicate test - _.findIndex = createPredicateIndexFinder(1); - _.findLastIndex = createPredicateIndexFinder(-1); - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) { low = mid + 1; } else { high = mid; } - } - return low; - }; - - // Generator function to create the indexOf and lastIndexOf functions - function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == 'number') { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; - } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), _.isNaN); - return idx >= 0 ? idx + i : -1; - } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) { return idx; } - } - return -1; - }; - } - - // Return the position of the first occurrence of an item in an array, - // or -1 if the item is not included in the array. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); - _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; - } - step = step || 1; - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Determines whether to execute a function as a constructor - // or a normal function with the provided arguments - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) { return sourceFunc.apply(context, args); } - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (_.isObject(result)) { return result; } - return self; - }; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = function(func, context) { - if (nativeBind && func.bind === nativeBind) { return nativeBind.apply(func, slice.call(arguments, 1)); } - if (!_.isFunction(func)) { throw new TypeError('Bind must be called on a function'); } - var args = slice.call(arguments, 2); - var bound = function() { - return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); - }; - return bound; - }; - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. _ acts - // as a placeholder, allowing any combination of arguments to be pre-filled. - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - var bound = function() { - var arguments$1 = arguments; - - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === _ ? arguments$1[position++] : boundArgs[i]; - } - while (position < arguments.length) { args.push(arguments$1[position++]); } - return executeBound(func, bound, this, this, args); - }; - return bound; - }; - - // Bind a number of an object's methods to that object. Remaining arguments - // are the method names to be bound. Useful for ensuring that all callbacks - // defined on an object belong to it. - _.bindAll = function(obj) { - var arguments$1 = arguments; - - var i, length = arguments.length, key; - if (length <= 1) { throw new Error('bindAll must be passed function names'); } - for (i = 1; i < length; i++) { - key = arguments$1[i]; - obj[key] = _.bind(obj[key], obj); - } - return obj; - }; - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = '' + (hasher ? hasher.apply(this, arguments) : key); - if (!_.has(cache, address)) { cache[address] = func.apply(this, arguments); } - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ - return func.apply(null, args); - }, wait); - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = _.partial(_.delay, _, 1); - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - if (!options) { options = {}; } - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) { context = args = null; } - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) { previous = now; } - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) { context = args = null; } - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; - - var later = function() { - var last = _.now() - timestamp; - - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - if (!timeout) { context = args = null; } - } - } - }; - - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) { timeout = setTimeout(later, wait); } - if (callNow) { - result = func.apply(context, args); - context = args = null; - } - - return result; - }; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - - // Returns a negated version of the passed-in predicate. - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var this$1 = this; - - var i = start; - var result = args[start].apply(this, arguments); - while (i--) { result = args[i].call(this$1, result); } - return result; - }; - }; - - // Returns a function that will only be executed on and after the Nth call. - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Returns a function that will only be executed up to (but not including) the Nth call. - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) { func = null; } - return memo; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = _.partial(_.before, 2); - - // Object Functions - // ---------------- - - // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. - var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); - var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', - 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - - function collectNonEnumProps(obj, keys) { - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; - - // Constructor is a special case. - var prop = 'constructor'; - if (_.has(obj, prop) && !_.contains(keys, prop)) { keys.push(prop); } - - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { - keys.push(prop); - } - } - } - - // Retrieve the names of an object's own properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = function(obj) { - if (!_.isObject(obj)) { return []; } - if (nativeKeys) { return nativeKeys(obj); } - var keys = []; - for (var key in obj) { if (_.has(obj, key)) { keys.push(key); } } - // Ahem, IE < 9. - if (hasEnumBug) { collectNonEnumProps(obj, keys); } - return keys; - }; - - // Retrieve all the property names of an object. - _.allKeys = function(obj) { - if (!_.isObject(obj)) { return []; } - var keys = []; - for (var key in obj) { keys.push(key); } - // Ahem, IE < 9. - if (hasEnumBug) { collectNonEnumProps(obj, keys); } - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - - // Returns the results of applying the iteratee to each element of the object - // In contrast to _.map it returns an object - _.mapObject = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = _.keys(obj), - length = keys.length, - results = {}, - currentKey; - for (var index = 0; index < length; index++) { - currentKey = keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [keys[i], obj[keys[i]]]; - } - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; - } - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) { names.push(key); } - } - return names.sort(); - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = createAssigner(_.allKeys); - - // Assigns a given object with all the own properties in the passed-in object(s) - // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) - _.extendOwn = _.assign = createAssigner(_.keys); - - // Returns the first key on an object that passes a predicate test - _.findKey = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = _.keys(obj), key; - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (predicate(obj[key], key, obj)) { return key; } - } - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(object, oiteratee, context) { - var result = {}, obj = object, iteratee, keys; - if (obj == null) { return result; } - if (_.isFunction(oiteratee)) { - keys = _.allKeys(obj); - iteratee = optimizeCb(oiteratee, context); - } else { - keys = flatten(arguments, false, false, 1); - iteratee = function(value, key, obj) { return key in obj; }; - obj = Object(obj); - } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) { result[key] = value; } - } - return result; - }; - - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj, iteratee, context) { - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - } else { - var keys = _.map(flatten(arguments, false, false, 1), String); - iteratee = function(value, key) { - return !_.contains(keys, key); - }; - } - return _.pick(obj, iteratee, context); - }; - - // Fill in a given object with default properties. - _.defaults = createAssigner(_.allKeys, true); - - // Creates an object that inherits from the given prototype object. - // If additional properties are provided then they will be added to the - // created object. - _.create = function(prototype, props) { - var result = baseCreate(prototype); - if (props) { _.extendOwn(result, props); } - return result; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) { return obj; } - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Returns whether an object has a given set of `key:value` pairs. - _.isMatch = function(object, attrs) { - var keys = _.keys(attrs), length = keys.length; - if (object == null) { return !length; } - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) { return false; } - } - return true; - }; - - - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) { return a !== 0 || 1 / a === 1 / b; } - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) { return a === b; } - // Unwrap any wrapped objects. - if (a instanceof _) { a = a._wrapped; } - if (b instanceof _) { b = b._wrapped; } - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) { return false; } - switch (className) { - // Strings, numbers, regular expressions, dates, and booleans are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN - if (+a !== +a) { return +b !== +b; } - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - } - - var areArrays = className === '[object Array]'; - if (!areArrays) { - if (typeof a != 'object' || typeof b != 'object') { return false; } - - // Objects with different constructors are not equivalent, but `Object`s or `Array`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - && ('constructor' in a && 'constructor' in b)) { - return false; - } - } - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - - // Initializing stack of traversed objects. - // It's done here since we only need them for objects and arrays comparison. - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) { return bStack[length] === b; } - } - - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - - // Recursively compare objects and arrays. - if (areArrays) { - // Compare array lengths to determine if a deep comparison is necessary. - length = a.length; - if (length !== b.length) { return false; } - // Deep compare the contents, ignoring non-numeric properties. - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) { return false; } - } - } else { - // Deep compare objects. - var keys = _.keys(a), key; - length = keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (_.keys(b).length !== length) { return false; } - while (length--) { - // Deep compare each member - key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) { return false; } - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return true; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) { return true; } - if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) { return obj.length === 0; } - return _.keys(obj).length === 0; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) === '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE < 9), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, 'callee'); - }; - } - - // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, - // IE 11 (#1621), and in Safari 8 (#1929). - if (typeof /./ != 'function' && typeof Int8Array != 'object') { - _.isFunction = function(obj) { - return typeof obj == 'function' || false; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj !== +obj; - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iteratees. - _.identity = function(value) { - return value; - }; - - // Predicate-generating functions. Often useful outside of Underscore. - _.constant = function(value) { - return function() { - return value; - }; - }; - - _.noop = function(){}; - - _.property = property; - - // Generates a function for a given object that returns a given property. - _.propertyOf = function(obj) { - return obj == null ? function(){} : function(key) { - return obj[key]; - }; - }; - - // Returns a predicate for checking whether an object has a given set of - // `key:value` pairs. - _.matcher = _.matches = function(attrs) { - attrs = _.extendOwn({}, attrs); - return function(obj) { - return _.isMatch(obj, attrs); - }; - }; - - // Run a function **n** times. - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) { accum[i] = iteratee(i); } - return accum; - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - - // A (possibly faster) way to get the current timestamp as an integer. - _.now = Date.now || function() { - return new Date().getTime(); - }; - - // List of HTML entities for escaping. - var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' - }; - var unescapeMap = _.invert(escapeMap); - - // Functions for escaping and unescaping strings to/from HTML interpolation. - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped - var source = '(?:' + _.keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - - // If the value of the named `property` is a function then invoke it with the - // `object` as context; otherwise, return it. - _.result = function(object, property, fallback) { - var value = object == null ? void 0 : object[property]; - if (value === void 0) { - value = fallback; - } - return _.isFunction(value) ? value.call(object) : value; - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\u2028|\u2029/g; - - var escapeChar = function(match) { - return '\\' + escapes[match]; - }; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - // NB: `oldSettings` only exists for backwards compatibility. - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) { settings = oldSettings; } - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escaper, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offest. - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) { source = 'with(obj||{}){\n' + source + '}\n'; } - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - try { - var render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled source as a convenience for precompilation. - var argument = settings.variable || 'obj'; - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function. Start chaining a wrapped Underscore object. - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var result = function(instance, obj) { - return instance._chain ? _(obj).chain() : obj; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result(this, func.apply(_, args)); - }; - }); - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) { delete obj[0]; } - return result(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - _.each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result(this, method.apply(this._wrapped, arguments)); - }; - }); - - // Extracts the result from a wrapped and chained object. - _.prototype.value = function() { - return this._wrapped; - }; - - // Provide unwrapping proxy for some methods used in engine operations - // such as arithmetic and JSON stringification. - _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; - - _.prototype.toString = function() { - return '' + this._wrapped; - }; - - // AMD registration happens at the end for compatibility with AMD loaders - // that may not enforce next-turn semantics on modules. Even though general - // practice for AMD registration is to be anonymous, underscore registers - // as a named module because, like jQuery, it is a base library that is - // popular enough to be bundled in a third party lib, but not be part of - // an AMD load request. Those cases could generate an error when an - // anonymous define() is called outside of a loader request. - if (typeof undefined === 'function' && undefined.amd) { - undefined('underscore', [], function() { - return _; - }); - } -}.call(commonjsGlobal)); -}); - -var Expression = { - display : - function() { - return this.exprType + " " + this.val; - }, - type : - function () { - return this.exprType; - }, - linenum : 0, - charnum : 0 -}; - -var TypeExpression = { - unify : - function (t) { - if (this.expr === t.expr) { - return t.expr; - } - else { - console.log("Could not unify " + this.expr + " with " + t.expr); - } - }, - isTypeExpr : true, - linenum : 0, - charnum : 0 -}; - -function flattenTypeDecl(stx) { - if (isTypeExpr(stx)) { - return true; - } - if (stx.exprType === "Application") { - /* it might be a type application so recursively check it */ - if (stx.p !== undefined) { - return underscore.flatten([flattenTypeDecl(stx.p), flattenTypeDecl(stx.func)]); - } - else { - return underscore.flatten([flattenTypeDecl(stx.func)]); - } - } - if (stx.exprType === "Name") { - /* - * Either it is a type operator - * or we assume it is a type variable - * since it was not capitalized - */ - return true; - } - return { - failed : true, - stx : stx - }; -} - - -function isTypeExprRec(stx) { - var flattened = flattenTypeDecl(stx); - for(var i = 0; i < flattened.length; i++) { - if (flattened[i].failed !== undefined && - flattened[i].failed) { - return flattened[i]; - } - } - return true; -} - -function Closure(bound_vars, free_vars, body, env) { - this.bound_vars = bound_vars; - this.free_vars = free_vars; - this.body = body; - this.env = env; - this.exprType = "Closure"; - return this; -} - -function LetExp(pairs, body) { - if (!pairs.every(function(x) { - return (x.exprType === "Definition" || - x.exprType === "FunctionDefinition"); - })) { - throw errors.JInternalError( - "let can only be used to bind things to names or functions" - ); - } - this.exprType = "Let"; - this.val = [pairs, body]; - this.pairs = pairs; - this.body = body; - return this; -} -LetExp.prototype = Expression; - -function UnaryOp(op, v) { - this.exprType = "Unary"; - this.val = v; - this.op = op; - return this; -} -UnaryOp.prototype = Expression; - -function IntT(v) { - this.exprType = "Integer"; - this.val = parseInt(v, 10); - return this; -} -IntT.prototype = Expression; - -function FloatT(v) { - this.exprType = "Float"; - this.val = parseFloat(v, 10); - return this; -} - -FloatT.prototype = Expression; - -function StrT(v) { - this.exprType = "String"; - this.val = v; - return this; -} - -StrT.prototype = Expression; - -function BoolT(b) { - if (b === "true") { - this.val = true; - } - else { - this.val = false; - } - this.exprType = "Bool"; - return this; -} - -BoolT.prototype = Expression; - -function ListT(xs) { - this.xs = xs; - this.val = xs; - this.exprType = "List"; - return this; -} - -ListT.prototype = Expression; - -function Nil() { - this.exprType = "Nil"; - return this; -} - -Nil.prototype = Expression; - - -function FuncT(p, body) { - this.p = p; - this.body = body; - this.val = [p, body]; - this.exprType = "Function"; - return this; -} - -FuncT.prototype = Expression; - -//Wrapper for function objects -function OpT(operator) { - this.op = operator; - this.val = this.op; - this.exprType = "Function"; - return this; -} - -OpT.prototype = Expression; - -// Applications separate from other types -function App(func, p) { - this.func = func; - this.exprType = "Application"; - if (p) - { this.p = p; } - return this; -} - -App.prototype = Expression; - -// Names are not types -function Name(identifier) { - this.ident = identifier; - this.val = this.ident; - this.exprType = "Name"; - return this; -} - -Name.prototype = Expression; - -function Def(ident, exp) { - this.ident = ident; - this.val = exp; - this.exprType = "Definition"; - return this; -} - -Def.prototype = Expression; - -function DefFunc(ident, params, body) { - this.ident = ident; - this.val = this.ident; - this.params = params; - this.body = body; - this.exprType = "FunctionDefinition"; - return this; -} - -DefFunc.prototype = Expression; - -function If(condition, thenexp, elseexp) { - this.condition = condition; - this.thenexp = thenexp; - this.elseexp = elseexp; - this.exprType = "If"; - return this; -} - -If.prototype = Expression; - -function TypeVar(name) { - this.exprtype = "TypeVar"; - this.name = name; - this.exprType = "TypeVar"; - return this; -} - -TypeVar.prototype = TypeExpression; - -function TypeOp(name) { - this.name = name; - this.val = name; - this.exprType = "TypeOperator"; - return this; -} - -TypeOp.prototype = TypeExpression; - -function isTypeExpr(expr) { - if (!expr.exprType) { - throw errors.JInternalError(expr); - } - return ((expr.exprType === "TypeOperator") || - (expr.exprType === "TypeVar") || - (expr.exprType === "TypeDeclaration")); -} - -function TypeDecl(expression, type) { - if (isTypeExprRec(expression) && - expression.exprType !== "Name") { - throw errors.JSyntaxError( - expression.linenum, - expression.charnum, - "Left-hand-side of type declaration must not be in the type language" - ); - } - if (isTypeExprRec(type).failed) { - throw errors.JInternalError( - "Right-hand-side of type declaration must be a type expression" - ); - } - this.expression = expression; - this.type = type; - this.exprType = "TypeDeclaration"; - return this; -} - -TypeDecl.prototype = TypeExpression; - -function DefType(lhs, rhs) { - /* Both rhs and lhs are expected - * to be fully desugared already - */ - if (isTypeExprRec(rhs).failed || - !isTypeExpr(lhs)) { - throw errors.JSyntaxError( - rhs.linenum, - rhs.charnum, - "Illegal type definition, both sides must be valid type expressions"); - } - this.rhs = rhs; - this.lhs = lhs; - this.exprType = "TypeDefinition"; - return this; -} - -DefType.prototype = Expression; - -function checkName(exp) { - if (exp.exprType !== "Name") { - throw errors.JSyntaxError( - exp.linenum, - exp.charnum, - "Expected a type variable (an identifier starting with a lowercase character), got " + exp.val); - } -} - -function DataType(name, params, type) { - /* Params is a list of type variables - * type is a type expression - */ - if (name.exprType !== "TypeOperator") { - throw errors.JSyntaxError( - name.linenum, - name.charnum, - "First element in a data type definition must be its name " + - "which is a type operator"); - } - underscore.each(params, checkName); - if (isTypeExprRec(type).failed) { - throw errors.JSyntaxError( - type.linenum, - type.charnum, - "Body of a type definition must be a valid type expression"); - } - this.name = name; - this.params = params; - this.type = type; - this.exprType = "TypeFuncDefinition"; - return this; -} - - -/* Applies the function ``name'' to the list of parameters */ -function makeApp(name, parameters) { - if (parameters) { - return parameters.slice(1).reduce(function(f, ident) { - return new App(f, ident); - }, new App(name, parameters[0])); - } - else { - return new App(name); - } -} - -function makeGensym() { - var n = 0; - return function() { - var x = "G"+n; - n = n + 1; - return x; - }; -} - -var gensym = makeGensym(); - -var OPInfo = { - "::" : [2, "Left"], - "," : [1, "Left"], - "->" : [1, "Right"] - }; - -var rep = { - IntT : IntT, - FloatT : FloatT, - StrT : StrT, - BoolT : BoolT, - ListT : ListT, - FuncT : FuncT, - App : App, - Name : Name, - Def : Def, - OpT : OpT, - OPInfo : OPInfo, - makeApp : makeApp, - If : If, - DefFunc : DefFunc, - UnaryOp : UnaryOp, - Nil : Nil, - LetExp : LetExp, - gensym : gensym, - TypeVar : TypeVar, - TypeOp : TypeOp, - TypeDecl : TypeDecl, - Closure : Closure, - isTypeExpr : isTypeExprRec, - DefType : DefType, - DataType : DataType - }; - -function empty(xs) { - return underscore.size(xs) < 1; -} - -function not(x) { - return !x; -} - -function min(a, b) { - if (a < b) { - return 1; - } - else if (a > b) { - return -1; - } - else { - return 0; - } -} - -function groupOps(ops) { - return underscore.groupBy(ops.sort(), underscore.isEqual); -} - -function dict(pairs) { - var o = {}; - pairs.map(function(p) { - o[p[0]] = p[1]; - }); - return o; -} - -function extend$1(xs, ys) { - var result = underscore.clone(xs); - result.push.apply(result, ys); - return result; -} - -RegExp.escape= function(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); -}; - -function operatorMatch(ops) { - ops = underscore.filter(ops, - function (op) { - return op.length > 0; - }); - ops.sort(min); - var rstring = ops.reduce( - function(acc, x) { - if (!x || x.length < 1) { - return ""; - } - return acc + "(" + RegExp.escape(x) + ")|"; - }, ""); - var reg = new RegExp(rstring); - return function(x) { - var matched = reg.exec(x); - if ((!(underscore.isNull(matched))) && matched[0]) { - return matched[0]; - } - else { - return false; - } - }; -} - -function debugPrint(stx) { - console.log("%j\n", stx); -} - - -var $$1 = { - not : not, - groupOps : groupOps, - opMatch : operatorMatch, - dict: dict, - extend : extend$1, - empty : empty, - debugPrint : debugPrint -}; - -var src = "\n;; This file declares the various types used by intrinsic/prelude definitions\n;; It is sort of special in that it doesn't care whether there are any associated definitions\n;; just that there are type definitions for that particular binding's name\n\n\n;; Type definitions\ndeftype String (Vector Char)\n\ndeftype (Int) Intrinsic\n\ndeftype (Float) Intrinsic\n\ndeftype (Char) Intrinsic\n\ndeftype (Byte) Intrinsic\n\ndeftype (Void) Intrinsic\n\ndeftype (IO a) Intrinsic\n\ndeftype (Vector a) Intrinsic\n\ndeftype (List a)\n (Empty |\n (Cons a (List a)))\n\ndeftype (Bottom)\n Undefined\n\ndeftype (Maybe a)\n (Nothing |\n (Just a))\n\ndeftype (Either a b)\n ((Left a) |\n (Right b))\n\n;; List functions\n\n(: :: (a -> (List a) -> (List a)))\n\n(map :: ((a -> b) -> (List a) -> (List b)))\n\n(head :: ((List a) -> a))\n\n(tail :: ((List a) -> (List a)))\n\n(!! :: (Int -> (List a) -> a))\n\n(take :: (Int -> (List a) -> (Maybe (List a))))\n\n(drop :: (Int -> (List a) -> (Maybe (List a))))\n\n;; Optional functions\n\n(maybe :: (b -> (a -> b) -> (Maybe a) -> b))\n\n(either :: ((b -> c) -> (b -> c) -> (Either a b) -> c))\n\n;; I/O functions\n\n(print :: (String -> (IO Void)))\n\n;; Operator definitions\n\ndefop 1 Left (a + b)\n (add a b)\n\ndefop 1 Left (a - b)\n (minus a b)\n\ndefop 2 Left (a * b)\n (mul a b)\n\ndefop 2 Left (a / b)\n (div a b)\n\ndefop 2 Right (a ^ b)\n (pow a b)\n\ndefop 3 Left (a ++ b)\n (listConcat a b)\n\ndefop 3 Left (a == b)\n (eq a b)\n\ndefop 3 Left (a > b)\n (gt a b)\n\ndefop 3 Left (a >= b)\n (gte a b)\n\ndefop 3 Left (a < b)\n (lt a b)\n\ndefop 3 Left (a <= b)\n (lte a b)\n\ndefop 3 Left (a && b)\n (and a b)\n\ndefop 3 Left (a || b)\n (or a b)\n\ndefop 4 Left (x : xs)\n (cons x xs)\n\ndefop 5 Left (f $ x)\n (fapply f x)\n\ndefop 5 Left (f . g)\n (compose f g)\n\ndefop 3 Left (a | b)\n (bitwiseOr a b)\n\ndefop 3 Left (a & b)\n (bitwiseAnd a b)"; - -var prelude = { - "src" : src -}; - -var operators = Object.keys(rep.OPInfo); - -function isDigit(c) { - if (!c) - { return false; } - var code = c.charCodeAt(); - if (isNaN(code)) { - return false; - } - return (47 < code) && (code < 58) -} - -function isWhitespace(c) { - if (!c) - { return true; } - - var code = c.charCodeAt(); - if (isNaN(code)) { - return true; - } - return (code === 9 || - code === 32 || - code === 10 || - code === 13 || - code === 11); -} - -function isIdentifier(c) { - var code = c.charCodeAt(); - return (!isNaN(code) && - code !== 41 && - code !== 40 && - code !== 125 && - code !== 123 && - code !== 93 && - code !== 91 && - code !== 44 && - code !== 34 && - code > 32); -} - -function isUpper(c) { - var code = c.charCodeAt(); - return (!isNaN(code) && - (code >= 65) && - (code <= 90)); -} - -function tokenizeNum(tokstream, charnum, linenum) { - var number = []; - var code = tokstream[0].charCodeAt(); - var isFloat = false; - var n = 0; - // + - - // might want to remove this since it probably won't ever get run? - if (code === 43 || code === 45) { // + or - - number.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - } - else if (code === 46) { // . - tokstream = tokstream.substr(1); - n++; - charnum++; - number.push('0'); - number.push('.'); - isFloat = true; - } - - while (isDigit(tokstream[0]) && tokstream.length !== 0) { - number.push(tokstream[0]); - tokstream = tokstream.substr(1); - charnum++; - n++; - } - if (tokstream[0] === '.' && isDigit(tokstream[1])) { - number.push('.'); - number.push(tokstream[1]); - tokstream = tokstream.substr(2); - charnum++; charnum++; - n++; n++; - while (isDigit(tokstream[0]) && tokstream.length !== 0) { - number.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - charnum++; - } - return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]]; - } - if (!isFloat) - { return [n, ["integer", parseInt(number.join(''), 10), charnum, linenum]]; } - else - { return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]]; } -} - -/* Split up the tokenized identifier if an operator appears in it - * prefer longer identifiers that start with the same character(s) as shorter ones - * e.g. ++ over + - * Everything after the operator goes back on to the token stream - */ - -function tokenizeIdent(tokstream, - matchop, - charnum, - linenum) { - var identifier = []; - var n = 0; - while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) { - identifier.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - charnum++; - } - identifier = identifier.join(''); - - return [[n, ["identifier", identifier, charnum, linenum]]]; -} - -function tokenizeCtor(tokstream, - matchop, - charnum, - linenum) { - var ident = tokenizeIdent(tokstream, - matchop, - charnum, - linenum); - ident[0][1][0] = "constructor"; - return ident; -} - -function tokenizeStr(tokstream, charnum, linenum) { - var stringlit = []; - var n = 1; - var new_charnum = charnum; - tokstream = tokstream.substr(1); - while (tokstream[0].charCodeAt() !== 34) { - stringlit.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - new_charnum++; - if (tokstream.length < 1) { - throw errors.JSyntaxError(linenum, charnum, "Error: missing quotation mark"); - } - } - n++; - return [n, ["stringlit", stringlit.join(''), new_charnum, linenum]]; - -} - -function tokenizeT(tokstream, charnum, linenum) { - if (tokstream.length < 4) - { return false; } - var next4 = tokstream.substr(0,4); - if (next4 === "then") - { return ["thenexp", "then"]; } - else if (next4 === "true") - { return ["truelit", "true"]; } - return false; -} - -function peek(tokstream, toktype, word, charnum, linenum) { - var n = word.length; - if (tokstream.length < n) - { return false; } - var nextN = tokstream.substr(0, n); - if (nextN == word) { - return [toktype, word]; - } - return false; -} - - -function tokenize(tokstream, matchop) { - var tokens = []; - var charnum = 1; - var linenum = 1; - var i, result, lambda, num, comment; - - while (tokstream) { - switch (tokstream[0].charCodeAt()) { - /* falls through */ - case 59: // ; - while (tokstream[0].charCodeAt() !== 10) { - tokstream = tokstream.substr(1); - } - break; - case 9: // '\t' - charnum++; - tokens.push(["whitespace", '\t', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 32: // ' ' - charnum++; - tokens.push(["whitespace", ' ', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 10: // '\n' - linenum++; - charnum = 1; /* Reset the character number for each line to 1 */ - tokens.push(["whitespace", '\n', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 44: // ',' - charnum++; - tokens.push(["comma", ",", charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 40: // '(' - charnum++; - tokens.push(["left_paren", '(', charnum, linenum]); - tokstream = tokstream.substr(1); - - break; - /* falls through */ - case 41: // ')' - charnum++; - tokens.push(["right_paren", ')', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 123: // '{' - charnum++; - tokens.push(["left_brace", '{', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 125: // '}' - charnum++; - tokens.push(["right_brace", '}', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 91: // '[' - charnum++; - tokens.push(["left_square", '[', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 93: // ']' - charnum++; - tokens.push(["right_square", ']', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 34: // '"' - result = tokenizeStr(tokstream, charnum, linenum); - var str = result[1]; - i = result[0]; - tokens.push(str); - tokstream = tokstream.substr(i); - break; - - /* falls through */ - case 46: // '.' - if (isDigit(tokstream[1])) { - result = tokenizeNum(tokstream, charnum, linenum); - num = result[1]; - i = result[0]; - if (!isNaN(num[1])) { - tokens.push(num); - } - tokstream = tokstream.substr(i); - break; - } - /* falls through */ - case 116: // 't' - result = tokenizeT(tokstream); - if (result) { - tokens.push($$1.extend(result, [charnum, linenum])); - tokstream = tokstream.substr(4); // 4 = length of either token - break; - } - /* falls through */ - case 105: // 'i' - var ifexp = peek(tokstream, "ifexp", "if"); - if (ifexp) { - tokens.push($$1.extend(ifexp, [charnum, linenum])); - tokstream = tokstream.substr(2); - break; - } - var inkeyword = peek(tokstream, "in", "in "); - if (inkeyword) { - tokens.push($$1.extend(inkeyword, [charnum, linenum])); - tokstream = tokstream.substr(3); - break; - } - - /* falls through */ - case 100: // 'd' - var defop = peek(tokstream, "defop", "defop"); - if (defop) { - tokens.push(["defop", "defop", charnum, linenum]); - tokstream = tokstream.substr(5); - break; - } - var deftype = peek(tokstream, "deftype", "deftype"); - if (deftype) { - tokens.push(["deftype", "deftype", charnum, linenum]); - tokstream = tokstream.substr(7); - break; - } - var def = peek(tokstream, "def", "def"); - if (def) { - tokens.push(["def", "def", charnum, linenum]); - tokstream = tokstream.substr(3); - break; - } - /* falls through */ - case 101: // e - result = peek(tokstream, "elsexp", "else"); - if (result) { - tokens.push($$1.extend(result, [charnum, linenum])); - tokstream = tokstream.substr(4); - break; - } - /* falls through */ - case 102: // f - result = peek(tokstream, "falselit", "false"); - if (result) { - tokens.push($$1.extend(result, [charnum, linenum])); - tokstream = tokstream.substr(5); - break; - } - /* falls through */ - case 108: // l - lambda = peek(tokstream, "lambda", "lambda"); - if (lambda) { - tokens.push($$1.extend(lambda, [charnum, linenum])); - tokstream = tokstream.substr(6); - break; - } - var letexp = peek(tokstream, "let", "let"); - if (letexp) { - tokens.push($$1.extend(letexp, [charnum, linenum])); - tokstream = tokstream.substr(3); - break; - } - - /* falls through */ - default: - if (isDigit(tokstream[0])) { - result = tokenizeNum(tokstream, charnum, linenum); - num = result[1]; - i = result[0]; - if (!isNaN(num[1])) { - tokens.push(num); - } - tokstream = tokstream.substr(i); - break; - } - var op = matchop(tokstream); - if (op) { - var l = op.length; - charnum = charnum + l; - tokstream = tokstream.substr(l); - tokens.push(["identifier", op, charnum, linenum]); - } - else { - if (isUpper(tokstream[0])) { - result = tokenizeCtor(tokstream, matchop, charnum, linenum); - } - else { - result = tokenizeIdent(tokstream, matchop, charnum, linenum); - } - for(var index = 0; index < result.length; index++) { - charnum++; - tokens.push(result[index][1]); - tokstream = tokstream.substr(result[index][0]); - } - } - } - } - return tokens; -} - -function tokenizeHelp(input, matchop, strip_whitespace) { - try { - return tokenize(input, matchop).reverse().filter(function(x) { - if (strip_whitespace) { - return x[0] !== "whitespace"; - } - else { - return true; - } - }); - } catch (e) { - console.log(e.stxerror()); - process.exit(1); - } -} - -var defop_pattern = ["defop", "integer", "constructor", - "left_paren", "identifier", - "identifier", "identifier", "right_paren"]; - -function checkPattern(x, i) { - return x === defop_pattern[i]; -} - -function tokenizeFull(input) { - var preludeSrc = prelude.src; - var matchop; - input = [preludeSrc, input].join(""); - var initialPass = tokenizeHelp(input, underscore.constant(false), true).reverse(); - - for (var i = 0; i < initialPass.length; i++) { - if (initialPass.slice(i, i+8). - map(underscore.first). - every(checkPattern)) { - rep.OPInfo[initialPass[i+5][1]] = - [parseInt(initialPass[i+1][1], 10), - initialPass[i+2][1]]; - } - } - operators = Object.keys(rep.OPInfo); - matchop = $$1.opMatch(operators); - return tokenizeHelp(input, matchop, true); -} - -var tokenizer = {tokenize : tokenizeFull, - isIdentifier : isIdentifier}; - -/* - * This module takes a parse tree in a surface format - * and transforms it into the "core" language which is - * much simpler and easier to type-check, optimize, and evaluate - */ - -function isAtomicNumber(stx) { - return stx.exprType == "Integer" || stx.exprType == "Float"; -} - -// Lists get desugared to nested function calls -// i.e. (cons (cons (cons ...))) -function desugarList(lst) { - if (lst.xs.length <= 0) { - return new rep.Nil(); - } - else { - var x = desugar(lst.xs[0]); - var rest = lst.xs.slice(1); - return new rep.App(new rep.App(new rep.Name("(:)"), x), desugarList(new rep.ListT(rest))); - } -} - -function desugarDefFunc(def) { - return new rep.Def(def.ident, - curryFunc(def.params, - def.body)); -} - -function curryFunc(ps, body) { - var result; - if (underscore.isEmpty(ps)) { - return desugar(body); - } - else { - result = new rep.FuncT(desugar(underscore.first(ps)), - curryFunc(underscore.rest(ps), body)); - result.charnum = ps.charnum; - result.linenum = ps.linenum; - return result; - } -} - - -function desugarLet(stx) { - var values = stx.pairs.map(desugar); - return new rep.LetExp(values, desugar(stx.body)); -} - -function sugarTypeDecl(stx) { - var type; - var expression; - type = stx.p; - expression = desugar(stx.func.p); - expression.linenum = stx.linenum; - expression.charnum = stx.charnum; - return new rep.TypeDecl(expression, type); -} - -function desugarDefType(stx, typeEnv) { - var result; - var rhs = desugar(stx.rhs); - var name = stx.lhs.name; - typeEnv[name] = rhs; - - result = new rep.DefType(stx.lhs, desugar(stx.rhs)); - result.linenum = stx.linenum; - result.charnum = stx.charnum; - return result; -} - -function desugar(stx, typeEnv) { - var typeExpTest; - - switch (stx.exprType) { - case "If": - if (stx.elseexp) { - return new rep.If(desugar(stx.condition, typeEnv), desugar(stx.thenexp, typeEnv), desugar(stx.elseexp, typeEnv)); - } - return new rep.If(desugar(stx.condition, typeEnv), desugar(stx.thenexp, typeEnv)); - case "FunctionDefinition": - return desugarDefFunc(stx); - case "Definition": - return new rep.Def(stx.ident, desugar(stx.val, typeEnv)); - case "TypeDefinition": - return desugarDefType(stx, typeEnv); - case "Name": - return stx; - case "Application": - if ((stx.func.func !== undefined ) && - (stx.func.func.ident === "::")) { - /* It's a type declaration probably (will be verified later) - * In this case we actually *add* syntax here to differentiate type declarations - * from normal function application - */ - typeExpTest = rep.isTypeExpr(stx.p); - - if (typeExpTest.failed !== undefined && - typeExpTest.failed) { - throw errors.JInternalError( - "Type declaration error near line " + stx.linenum + " at character #"+stx.charnum + - "\n"+typeExpTest.stx.exprType+" (" + typeExpTest.stx.val + ") found where a type operator or type application was expected"); - } - return sugarTypeDecl(stx); - } - - if ((stx.func.ident === "-") && - stx.p && isAtomicNumber(stx.p)) { - console.log("Matched unary"); - console.log(stx); - return new rep.UnaryOp(desugar(stx.func, typeEnv), desugar(stx.p, typeEnv)); - } - if (stx.p) { - return new rep.App(desugar(stx.func, typeEnv), desugar(stx.p, typeEnv)); - } - return new rep.App(stx.func); - case "Function": - return curryFunc(stx.p, stx.body); - case "List": - return desugarList(stx); - case "Bool": - return stx; - case "String": - return stx; - case "Float": - return stx; - case "Integer": - return stx; - case "Let": - return desugarLet(stx); - default: - return stx; - } -} - -var desugarer = { desugar : desugar }; -//var test = typ.ListT([1,2,3]); - -//console.log(desugarList(test)); - -/* Takes an AST and converts all of the functions into "closures" - * A closure is a triple of: - * the bound variables in a function or let - * the free variables in a function or let - * a function body or let body and bound values (if it is an escaping closure only) - * The closure has the property that all of the free variables of the function or let - * are in the environment, or an exception is raised because the variable is not bound - * in the current environment. - * A free variable is simply those that are not in the list of formal parameters or bound variables if it is a let - * - * Therefore in order to call a closure one must first extract the actual function and then - * call the function with the environment associated with it. - * For the purposes of type checking it does not matter how the function gets called, the environment - * is only used for looking up the types of names. Formal parameters are given type variables. - * - * The first phase of closure conversion is not really closure conversion exactly. - * All it does is find out the free variables in scope and tie those up into a data structure with their types later. - * The second phase will be done to the CPS language and closures will actually lambda-lifted out potentially. - */ - -var notEmpty = underscore.compose($$1.not, underscore.partial(underscore.equal, [])); - -function fvs(stx) { - switch (stx.exprType) { - case "Integer": - return []; - case "Float": - return []; - case "String": - return []; - case "Function": - return []; - case "Nil": - return []; - case "Bool": - return []; - case "Let": - return []; - case "Unary": - return underscore.flatten([stx.op.ident, fvs(stx.val)]); - case "Definition": - return underscore.flatten(fvs(stx.val)); - case "Application": - var vs = underscore.flatten(fvs(stx.p)); - var f_fvs = underscore.flatten(fvs(stx.func)); - return underscore.flatten([vs, f_fvs]); - case "If": - if (stx.elseexp) { - var cond_fvs = fvs(stx.condition); - var then_fvs = fvs(stx.thenexp); - var else_fvs = fvs(stx.elseexp); - return underscore.flatten([cond_fvs, then_fvs, else_fvs]); - } - else { - return underscore.flatten([fvs(stx.condition), fvs(stx.thenexp)]); - } - break; - case "Name": - return [stx.ident]; - } -} - -function annotate_fvs(stx) { - /* Takes a stx object that is either - * a lambda - * a let - * and returns a closure wrapped around that stx object - */ - if (stx.exprType !== "Function" && - stx.exprType !== "Let") { - throw errors.JInternalError( - ["Tried to calculate the free variables of", - "something that was not a function or let.\n", - "That something was a: " + stx.exprType +"\n"].reduce( - function (a,b) { - return a+" "+b; - }, "")); - } - var variables, free_variables, bound_vars, stx_type; - - switch (stx.exprType) { - case "Let": - bound_vars = stx.pairs.map( - function (stx) { - return stx.ident.ident; - }); - var let_fvs = stx.pairs.map(fvs); - var body_fvs = fvs(stx.body); - variables = underscore.flatten(let_fvs); - $$1.extend(variables, underscore.flatten(body_fvs)); - break; - case "Function": - bound_vars = [stx.p.ident ]; - variables = fvs(stx.body); - break; - } - free_variables = underscore.difference(underscore.uniq(variables), bound_vars); - return new rep.Closure(bound_vars, free_variables, stx, []); -} - -/* - * This traverse the tree and gathers up all of the free variables of various functions/let bindings - */ -function annotate_fvs_all(stx) { - var closure; - switch (stx.exprType) { - case "Let": - closure = annotate_fvs(stx); - closure.body.pairs = closure.body.pairs.map(annotate_fvs_all); - closure.body = annotate_fvs_all(closure.body.body); - return closure; - case "Function": - closure = annotate_fvs(stx); - closure.body.body = annotate_fvs_all(closure.body.body); - return closure; - case "Unary": - stx.val = annotate_fvs_all(stx.val); - return stx; - case "Application": - stx.func = annotate_fvs_all(stx.func); - stx.p = annotate_fvs_all(stx.p); - return stx; - case "If": - if (stx.elseexp) { - stx.condition = annotate_fvs_all(stx.condition); - stx.thenexp = annotate_fvs_all(stx.thenexp); - stx.elseexp = annotate_fvs_all(stx.elseexp); - return stx; - } - else { - stx.condition = annotate_fvs_all(stx.condition); - stx.thenexp = annotate_fvs_all(stx.thenexp); - return stx; - } - break; - case "Definition": - stx.val = annotate_fvs_all(stx.val); - return stx; - default: - return stx; - } -} - - -//console.log(test("if something then if a then if b then c else d else rtrrt else some_other_thing")); -var closure = { - annotate_fvs : annotate_fvs_all -}; - -function sourcePos(tokens, linenum, charnum) { - if (!tokens || tokens.length === 0) { - return { linenum : linenum, - charnum : charnum - }; - } - return { - linenum : fst(tokens)[3], - charnum : fst(tokens)[2] - }; -} - -function addSrcPos(stx, tokens, linenum, charnum) { - var pos = sourcePos(tokens, linenum, charnum); - stx.linenum = pos.linenum; - stx.charnum = pos.charnum; - return stx; -} - -/* Gets the first token from the right side of the stack */ -function fst(ts) { - return ts[ts.length-1]; -} - -/* Gets the second token from the right side of the stack */ -function snd(ts) { - return ts[ts.length-2]; -} - -/*Checks if the next token is not followed by any of ``checks'' */ -function notFollowedBy(tokens, checks, linenum, charnum) { - if (!fst(tokens)) { - throw errors.JSyntaxError(0,0,"unexpected end of source"); - } - var nextT = fst(tokens)[0]; - if (checks.some(function (x) { - return x === nextT; - })) - { return false; } - else - { return true; } -} - -/* returns a function that takes a parameter and - checks if it is in the array ``props''*/ -function makeChecker(props) { - return function(x) { - return x && props.some(function (y) {return y(x);}); - }; -} - -function tokTypeCheck(name) { - return function(tok) { - return tok[0] === name; - }; -} - -function formTypeCheck(stxtype) { - return function(stx) { - return stx.exprType === stxtype; - }; -} - -/*Tries to parse until the prediction ``valid'' fails or the wrong type is parsed - Collects the results into an array and returns it*/ -function parseMany(parse, exprType, valid, tokens, charnum, linenum) { - if (!fst(tokens)) { - throw errors.JSyntaxError(charnum, - linenum, - "Unexpected end of source"); - } - var current = fst(tokens)[0]; - var results = []; - var parsed; - - if (valid(fst(tokens))) { - parsed = parse(tokens); - } - else { - throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Unexpected token: ``"+fst(tokens)[0]+"''"); - } - results.push(parsed); - - //make sure there are at least 2 tokens to parse - if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) { - while (valid(snd(tokens))) { - if (!(valid(fst(tokens)))) { - break; - } - results.push(parse(tokens)); - if (!exprType(fst(results).exprType)) { - break; - } - if (fst(tokens)) { - current = fst(tokens)[0]; - } - else { - throw errors.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - if (tokens.length <= 1) { - break; - } - } - } - //do the same validity check as before and in the loop - if (!fst(tokens)) { - throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "unexpected end of source"); - } - if (valid(fst(tokens))) { - results.push(parse(tokens)); - } - return results; -} - - -/* Tries to parse exprType separated by the token between - * e.g. ,,... - */ -function parseBetween(exprType, between, tokens, charnum, linenum) { - var first = parse(tokens); - var items; - var parsed; - - if (!exprType(first)) { - throw errors.JSyntaxError(fst(tokens)[2], fst(tokens)[3], "Unexpected token: ``"+fst(tokens)[0]+"''"); - } - - items = [first]; - - if (tokens.length > 1 && fst(tokens)[0] === between) { - while (fst(tokens)[0] === between) { - tokens.pop(); - parsed = parse(tokens); - if (!fst(tokens)) - { throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Missing terminator: "+between); } - items.push(parsed); - } - return items; - } - return items; -} - -function parseList(tokens, linenum, charnum) { - var xs; - var result; - - if (fst(tokens)[0] === "right_square") { - xs = []; - } - else if (fst(tokens)[0] === "comma") { - tokens.pop(); - xs = []; - } - else { - xs = parseBetween(function (x) { - return true; - }, "comma", tokens, fst(tokens)[3], fst(tokens)[2]); - } - if (!fst(tokens) || fst(tokens)[0] !== "right_square") { - throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "list must be terminated by ]"); - } - tokens.pop(); - result = addSrcPos(new rep.ListT(xs), tokens, linenum, charnum); - return result; -} - - -function parseDefFunction(tokens, linenum, charnum) { - var fname = parse(tokens); - var parameters; - var result; - var body; - - if (fname.exprType !== "Name") { - throw errors.JSyntaxError(linenum, - charnum, - "Expected an identifier in function definition"); - } - if (fst(tokens)[0] === "right_paren") { - parameters = []; - } - else { - parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - } - if (!tokens || (fst(tokens)[0]) !== "right_paren") { - throw errors.JSyntaxError(linenum, - charnum, - "Formal parameters must be followed by )"); - } - tokens.pop(); - body = parse(tokens); - result = addSrcPos(new rep.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum); - return result; -} - -var validLet = makeChecker(["Definition", "FunctionDefinition"].map(formTypeCheck)); -var letEnd = underscore.compose($$1.not, makeChecker(["right_brace"].map(tokTypeCheck))); - -function parseLetForm(tokens, linenum, charnum) { - var result; - var pairs; - var body; - - if (!fst(tokens)) { - errors.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - pairs = parseMany(parseLetItem, - validLet, - letEnd, - tokens, - charnum, - linenum); - if (fst(tokens) && fst(tokens)[0] !== "right_brace") { - throw errors.JSyntaxError(fst(tokens)[2], - fst(tokens)[3], - "let/def form must have a closing }"); - } - if (!fst(tokens)) { - throw errors.JSyntaxError(underscore.last(pairs).linenum, - underscore.last(pairs).charnum, - "Unexpected end of source"); - } - tokens.pop(); - if (tokens.length <= 0) { - throw errors.JSyntaxError(underscore.last(pairs).linenum, - underscore.last(pairs).charnum, - "let/def form must have a body"); - } - body = parse(tokens); - if (body.exprType === "Definition" || - body.exprType === "FunctionDefinition") { - throw errors.JSyntaxError(body.linenum, - body.charnum, - "Body of a let/def expression cannot be a definition"); - } - result = addSrcPos(new rep.LetExp(pairs, body), tokens, body.linenum, body.charnum); - return result; - -} - -function parseLetFunction(tokens, linenum, charnum) { - var fname = parse(tokens); - var parameters; - var result; - var body; - - if (fname.exprType != "Name") { - throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Expected an identifier in function definition"); - } - if (fst(tokens)[0] === "right_paren") { - parameters = []; - } - else { - parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - } - if ((fst(tokens)[0]) !== "right_paren") { - throw errors.JSyntaxError(linenum, - charnum, - "Formal parameters must be followed by )"); - } - tokens.pop(); - if (fst(tokens)[1] !== "->") { - throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Function parameters in let/def form must be followed by ->"); - } - tokens.pop(); - body = parse(tokens); - result = addSrcPos(new rep.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum); - return result; -} - -function parseLetBinding(tokens, linenum, charnum) { - var name = parse(tokens); - var result; - var bound; - - if (name.exprType != "Name") { - throw errors.JSyntaxError(name.linenum, - name.charnum, - "Expected an identifier in let/def binding"); - } - if (!fst(tokens) || fst(tokens)[1] !== "=") { - throw errors.JSyntaxError(name.linenum, - name.charnum, - "An identifier in a let/def binding must be followed by ``=''"); - } - tokens.pop(); - if (!notFollowedBy(tokens, - ["comma", "arrow", "right_brace", "right_square"], - name.linenum, - name.charnum)) { - throw errors.JSyntaxError(name.linenum, - name.charnum, - "The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]); - } - bound = parse(tokens); - if (bound.exprType === "Definition" || - bound.exprType === "FunctionDefinition") { - throw errors.JSyntaxError(bound.linenum, - bound.charnum, - "A definition cannot be the value of a binding"); - } - result = addSrcPos(new rep.Def(name, bound), tokens, bound.linenum, bound.charnum); - return result; -} - -function parseLetItem(tokens) { - var linenum = fst(tokens)[3]; - var charnum = fst(tokens)[2]; - - if (fst(tokens) && fst(tokens)[0] === "left_paren") { - tokens.pop(); - return parseLetFunction(tokens, - linenum, - charnum); - } - else { - return parseLetBinding(tokens, - linenum, - charnum); - } -} - -function parseDataType(tokens, linenum, charnum) { - var typeName = parse(tokens, linenum, charnum); - var typeParams; - var typeBody; - var result; - - if (typeName.exprType !== "TypeOperator") { - throw errors.JSyntaxError(typeName.linenum, - typeName.charnum, - "Expected a type operator in data type definition"); - } - if (fst(tokens)[0] !== "right_paren") { - var parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - } - else { - var parameters = []; - } - if (!tokens || (fst(tokens)[0]) !== "right_paren") { - throw errors.JSyntaxError(underscore.last(parameters).linenum, - underscore.last(parameters).charnum, - "Data type parameters must be followed by )"); - } - tokens.pop(); - typeBody = parse(tokens); - result = addSrcPos(new rep.DataType(typeName, parameters, typeBody), tokens, typeBody.linenum, typeBody.charnum); - - return result; -} - - - -function parseDefType(tokens, linenum, charnum) { - var result; - var rhs; - var lhs; - - if (tokens.length < 2) { - /* Minimal number of tokens required is 2 - * because it could be 'deftype Foo Blah' - */ - throw errors.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - if (fst(tokens)[0] === "left_paren") { - /* It's an actual data type definition - * i.e. not just an alias - */ - tokens.pop(); - return parseDataType(tokens, linenum, charnum); - } - - if (notFollowedBy(tokens, ["constructor"], linenum, charnum)) { - throw errors.JSyntaxError(linenum, - charnum, - "deftype must be followed by a single constructor" + - " if it is not a data type definition with type variables"); - } - else { - lhs = parse(tokens, linenum, charnum); - if (!tokens) { - throw errors.JSyntaxError(lhs.linenum, - lhs.charnum, - "Unexpected end of source"); - } - if (lhs.exprType !== "TypeOperator") { - throw errors.JSyntaxError(lhs.linenum, - lhs.charnum, - "left-hand side of type alias was not a type operator"); - } - rhs = parse(tokens, linenum, charnum); - - if (rhs.exprType !== "Application" && - rhs.exprType !== "TypeOperator") { - throw errors.JSyntaxError(rhs.linenum, - rhs.charnum, - "was expecting an application or type operator on the right-hand side of a type alias"); - } - result = addSrcPos(new rep.DefType(lhs, rhs), tokens, rhs.linenum, rhs.charnum); - return result; - } -} - - - - - -function parseDef(tokens, linenum, charnum) { - var result; - var identifier; - var bound; - - if (tokens.length < 2) { - /* Minimal number of tokens required is 2 - * because it could be 'def foo blah' - */ - throw errors.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - if (fst(tokens)[0] === "left_paren") { - /* It's a function definition */ - tokens.pop(); - return parseDefFunction(tokens, linenum, charnum); - } - - if (fst(tokens)[0] === "left_brace") { - /* It's a let/def form */ - tokens.pop(); - return parseLetForm(tokens, - fst(tokens)[3], - fst(tokens)[2]); - } - - if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) { - throw errors.JSyntaxError(linenum, - charnum, - "def must be followed by identifier, not "+fst(tokens)[0]); - } - else { - identifier = parse(tokens); - if (!fst(tokens)) - { throw errors.JSyntaxError(identifier.linenum, - identifier.charnum, - "Unexpected end of source"); } - if (!notFollowedBy(tokens, - ["comma", "arrow", "right_brace", "right_square"], - identifier.linenum, - identifier.charnum)) { - throw errors.JSyntaxError(identifier.linenum, - identifier.charnum, - "def " + identifier.val + " must not be followed by " + fst(tokens)[0]); - } - bound = parse(tokens); - if (bound.exprType === "Definition" || - bound.exprType === "FunctionDefinition") { - throw errors.JSyntaxError(bound.linenum, - bound.charnum, - "A definition cannot be the value of a binding"); - } - result = addSrcPos(new rep.Def(identifier, bound), tokens, bound.linenum, bound.charnum); - return result; - } - } - -function parseDefOp(tokens, linenum, charnum) { - var result; - var names; - var pattern; - - if (fst(tokens)[0] !== "integer" || - fst(tokens)[1] < 1) { - throw errors.JSyntaxError(linenum, - charnum, - "defop must be followed by integer precedence >= 1"); - } - tokens.pop(); - - if (fst(tokens)[1] !== "Left" && fst(tokens)[1] !== "Right") { - throw errors.JSyntaxError(linenum, - charnum, - "defop must be followed by precedence and then either Left or Right"); - } - tokens.pop(); - if (fst(tokens)[0] !== "left_paren") { - throw errors.JSyntaxError(linenum, - charnum, - "defop arguments must start with ("); - } - tokens.pop(); - if (!(tokens.slice(tokens.length-3, - tokens.length).every(function(x) { - return x[0] === "identifier"; - }))) { - throw errors.JSyntaxError(linenum, - charnum, - "defop must be surrounded by exactly 3 identifiers"); - } - pattern = tokens.slice(tokens.length-3, - tokens.length); - tokens.pop(); tokens.pop(); tokens.pop(); - if (fst(tokens)[0] !== "right_paren") { - throw errors.JSyntaxError(linenum, - charnum, - "defop pattern must be terminated with )"); - } - tokens.pop(); - names = [new rep.Name(pattern[1][1]), - new rep.Name(pattern[0][1]), - new rep.Name(pattern[2][1])]; - names.map(function(name) { - name.linenum = linenum; - name.charnum = charnum; - return name; - }); - - result = addSrcPos(new rep.DefFunc(names[0], - names.slice(1,3), - parse(tokens)), - tokens, - underscore.last(names).linenum, - underscore.last(names).charnum); - return result; -} - - - -function parseIf(tokens, linenum, charnum) { - var result; - var ifC; - var thenC; - var elseC; - - if (!notFollowedBy(tokens, - ["def","comma","lambda"], - linenum, - charnum)) { - throw errors.JSyntaxError(linenum, - charnum, - "``if'' cannot be followed by "+fst(tokens)[0]) ; - } - else { - ifC = parse(tokens); - if (!fst(tokens) || fst(tokens)[0] !== "thenexp") { - throw errors.JSyntaxError(ifC.linenum, - ifC.charnum, - "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]); - } - else { - tokens.pop(); - thenC = parse(tokens); - - if (fst(tokens) && fst(tokens)[0] === "elsexp") { - tokens.pop(); - if (underscore.size(tokens) < 1) { - throw errors.JSyntaxError(thenC.linenum, - thenC.charnum, - "Unexpected end of source"); - } - else { - elseC = parse(tokens); - result = addSrcPos(new rep.If(ifC, thenC, elseC), tokens, elseC.linenum, elseC.charnum); - return result; - } - } - else { - throw errors.JSyntaxError(thenC.linenum, - thenC.charnum, - "If expression must include an else variant"); - } - } - } -} - -var validName = makeChecker(["Name"].map(formTypeCheck)); - -function validFormPar(tok) { - return tok[0] === "identifier" && - tok[1] !== "->"; -} - -function parseLambda(tokens, linenum, charnum) { - var result; - var parameters = parseMany(parse, - validName, - validFormPar, - tokens, - charnum, - linenum); - if (fst(tokens)[1] !== "->") { - throw errors.JSyntaxError(underscore.last(parameters).linenum, - underscore.last(parameters).charnum, - "arrow must follow parameters in lambda, not "+fst(tokens)[0]); - } - tokens.pop(); - var body = parse(tokens); - result = addSrcPos(new rep.FuncT(parameters, body), tokens, body.linenum, body.charnum); - return result; -} - -var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"].map(tokTypeCheck); -var validArgument = underscore.compose($$1.not, makeChecker(invalidArguments)); -var validArgTypes = underscore.compose($$1.not, makeChecker(["Definition"].map(formTypeCheck))); - -/* Parses function application (either infix or prefix) */ -function computeApp(tokens, charnum, linenum) { - var lhs = parse(tokens); - var next; - var result; - var parameters; - - if (fst(tokens)) { - next = fst(tokens); - } - else { - throw errors.JSyntaxError(lhs.linenum, - lhs.charnum, - "Unexpected end of source"); - } - if (rep.OPInfo[next[1]]) { - /* it's an infix expression */ - result = parseInfix(tokens, 1, lhs, lhs.linenum, lhs.charnum); - if (!fst(tokens) || fst(tokens)[0] !== "right_paren") { - throw errors.JSyntaxError(lhs.linenum, - lhs.charnum, - "Mismatched parentheses or missing parenthesis on right-hand side"); - } - else { - tokens.pop(); - return result; - } - } - else { - /* it's a prefix application */ - if (fst(tokens)[0] !== "right_paren") { - parameters = parseMany(parse, - validArgTypes, - validArgument, - tokens, - fst(tokens)[2], - fst(tokens)[3]); - } - else { - parameters = []; - } - if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") { - throw errors.JSyntaxError(fst(tokens)[3], - fst(tokens)[2], - "Mismatched parentheses or missing parenthesis on right-hand side"); - } - else { - tokens.pop(); - return addSrcPos(rep.makeApp(lhs, parameters), tokens, linenum, charnum); - } - } -} - -/*Parses infix expressions by precedence climbing - * console.log(stx); - See this for more info and an implementation in python - http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/ -*/ -function parseInfix(tokens, minPrec, lhs, linenum, charnum) { - if (!lhs) { - lhs = parse(tokens); - } - while (true) { - var cur = fst(tokens); - if (!cur) { - throw errors.JSyntaxError(linenum, - charnum, - "Unexpected end of source"); - } - var opinfo = rep.OPInfo[cur[1]]; - - if (!opinfo || opinfo[0] < minPrec) - { break; } - - var op = addSrcPos(new rep.Name(cur[1]), tokens, linenum, charnum); - var prec = opinfo[0]; - var assoc = opinfo[1]; - var nextMinPrec = assoc === "Left" ? prec + 1 : prec; - tokens.pop(); - /*remove the operator token*/ - var rhs = parseInfix(tokens, nextMinPrec); - lhs = addSrcPos(rep.makeApp(op, [lhs, rhs]), tokens, rhs.linenum, rhs.charnum); - } - return lhs; -} - -function parse(tokens) { - var charnum = fst(tokens)[2]; - var linenum = fst(tokens)[3]; - var toktype; - var result; - if (fst(tokens)) { - toktype = fst(tokens)[0]; - } - else { - console.error("Tokenization error"); - } - var token = fst(tokens)[1]; - tokens.pop(); - if (toktype === "stringlit") { - result = addSrcPos(new rep.StrT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "left_square") { - return parseList(tokens, linenum, charnum); - } - else if (toktype === "lambda") { - return parseLambda(tokens, linenum, charnum); - } - else if (toktype === "integer") { - result = addSrcPos(new rep.IntT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "float") { - result = addSrcPos(new rep.FloatT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "identifier") { - result = addSrcPos(new rep.Name(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "constructor") { - result = addSrcPos(new rep.TypeOp(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "truelit" || toktype === "falselit") { - result = addSrcPos(new rep.BoolT(token), tokens, linenum, charnum); - return result; - } - else if (toktype === "def" || - toktype === "let") { - return parseDef(tokens, linenum, charnum); - } - else if (toktype === "deftype") { - return parseDefType(tokens, linenum, charnum); - } - else if (toktype === "defop") { - return parseDefOp(tokens, linenum, charnum); - } - else if (toktype === "ifexp") { - return parseIf(tokens, linenum, charnum); - } - else if (toktype === "left_paren") { - if (fst(tokens)[0] === "lambda") { - tokens.pop(); - var parsed = parseLambda(tokens, linenum, charnum); - tokens.pop(); - return parsed; - } - else - { return computeApp(tokens, linenum, charnum); } - } - else { - throw errors.JSyntaxError(linenum, - charnum, - "Unexpected token: ``" + toktype+"''"); - } -} - - -function parseFull(tokenized) { - var ast = []; - var typeBindings = {}; - var current; - try { - while (tokenized.length > 0) { - current = closure.annotate_fvs(desugarer.desugar(parse(tokenized), typeBindings)); - ast.push(current); - } - return { - "ast" : ast, - "types" : typeBindings - }; - } catch (e) { - if (e.stxerror !== undefined) { - e.stxerror(); - console.error("Tokenization error"); - } - else { - console.log(e.errormessage); - } - } -} - -var parser = { parse : function(str) { - return parseFull(tokenizer.tokenize(str)); - }, - tokenize : tokenizer.tokenize, - parseFull : parseFull, - }; -//var testParse = parseFull(tokenizer.tokenize(istr)); -//console.log(testParse[1]); -//console.log(testParse[0].map(pprint.pprint)); - -/* - * An environment is just an object that maps identifiers to JLambda expressions - * with a few built-in (a standard Prelude environment) - */ - -// creates a new environment initialized with the pairs in values -function makeEnv(name, values) { - var env = {}; - env.name = name; - env.bindings = {}; - for (var i = 0; i < values.length; i++) { - name = values[i][0]; - var val = values[i][1]; - env.bindings[name] = val; - } - return env; -} - -function lookup$1(name, env) { - var value = env.bindings[name]; - if (!value) { - throw errors.JUnboundError(name, env.name); - } - return value; -} - -var env = { - lookup : lookup$1, - makeEnv : makeEnv -}; - -var testenv = env.makeEnv("toplevel", - [ - ["+", function(a) { return function(b) { return a + b; } }], - ["*", function(a) { return function(b) { return a * b; } }], - ["-", function(a) { return function(b) { return a - b; } }], - ["/", function(a) { return function(b) { return a / b; } }], - ["a", 2], - ["b", 3]]); - -function lookup(ident, env$$1) { - var func = evaluate(env$$1.bindings[ident], env$$1); - return func; -} - -function evaluateString(input) { - var ast = parser.parseFull(tokenizer.tokenize(input)); - return evaluate(ast.ast[ast.ast.length-1], testenv); -} - -function apply(func, p) { - return func(evaluate(p)); -} - -function evaluate(ast, environment) { - if (ast.exprType == "Application") { - var func = evaluate(ast.func, environment); - return apply( - func, - evaluate(ast.p, environment)); - } - else if (ast.exprType === "Unary") { - /* Unary function application */ - var func = evaluate(ast.op, environment); - return apply( - func, - evaluate(ast.val, environment)); - } - else if (ast.exprType === "Name") { - return lookup(ast.ident, environment); - } - else if (ast.exprType === "If") { - if (evaluate(ast.condition, environment)) { - return evaluate(ast.thenexp, environment); - } - else { - return evaluate(ast.elseexp, environment); - } - } - else if (ast.exprType === "Definition") { - return; /* XXX */ - } - else if (ast.exprType === "Integer" || ast.exprType == "Float") { - return ast.val; - } - else { - return ast; - } -} - -var vm = { - evaluateString : evaluateString -}; - -riot$1.tag2('test', ' ', '', '', function(opts) { - -this.evaluate = function() { - var input = this.refs.input; - alert(vm.evaluateString(input.value)); -}.bind(this); - -}); - -riot$1.mount("test"); - -}()); +!function(){"use strict";function e(e){return Rn.test(e)}function t(e){return typeof e===Nn}function n(e){return e&&typeof e===Sn}function r(e){return typeof e===kn}function i(e){return typeof e===En}function o(e){return r(e)||null===e||""===e}function a(e){return Array.isArray(e)||e instanceof Array}function u(e,t){var n=Object.getOwnPropertyDescriptor(e,t);return r(e[t])||n&&n.writable}function s(e){return Cn.test(e)}function c(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function f(e,t){return(t||document).querySelector(e)}function p(){return document.createDocumentFragment()}function l(){return document.createTextNode("")}function h(e){return!!e.ownerSVGElement}function d(e){return"svg"===e?document.createElementNS(An,e):document.createElement(e)}function m(e,t){if(r(e.innerHTML)){var n=(new DOMParser).parseFromString(t,"application/xml"),i=e.ownerDocument.importNode(n.documentElement,!0);e.appendChild(i)}else e.innerHTML=t}function y(e,t){e.style.display=t?"":"none",e.hidden=!t}function v(e,t){e.removeAttribute(t)}function g(e){return Object.keys(e).reduce(function(t,n){return t+" "+n+": "+e[n]+";"},"")}function x(e,t){return e.getAttribute(t)}function b(e,t,n){var r=jn.exec(t);r&&r[1]?e.setAttributeNS(On,r[1],n):e.setAttribute(t,n)}function w(e,t,n){e.insertBefore(t,n.parentNode&&n)}function _(e,t){if(e)for(var n;n=Dn.exec(e);)t(n[1].toLowerCase(),n[2]||n[3]||n[4])}function T(e,t,n){if(e){var r,i=t(e,n);if(!1===i)return;for(e=e.firstChild;e;)r=e.nextSibling,T(e,t,i),e=r}}function E(e,t){for(var n=e?e.length:0,r=0;rr;)n--,R.apply(t[n],[t,n])}function R(e,t){e.splice(t,1),this.unmount(),he(this.parent,this,this.__.tagName,!0)}function U(e){var t=this;E(Object.keys(this.tags),function(n){ae.apply(t.tags[n],[n,e])})}function B(e,t,n){n?ve.apply(this,[e,t]):w(e,this.root,t.root)}function P(e,t,n){n?ye.apply(this,[e,t]):w(e,this.root,t.root)}function z(e,t){t?ye.call(this,e):e.appendChild(this.root)}function $(e,t,n){v(e,xn);var r,o=typeof x(e,bn)!==En||v(e,bn),u=fe(e),s=hn[u],c=e.parentNode,f=l(),h=ie(e),d=x(e,gn),m=[],y=[],g=!hn[u],b="VIRTUAL"===e.tagName;return n=Wn.loopKeys(n),n.isLoop=!0,d&&v(e,gn),c.insertBefore(f,e),c.removeChild(e),n.update=function(){n.value=Wn(n.val,t);var c=p(),l=n.value,v=!a(l)&&!i(l),x=f.parentNode;x&&(v?l=(r=l||!1)?Object.keys(l).map(function(e){return D(n,l[e],e)}):[]:r=!1,d&&(l=l.filter(function(e,r){return n.key&&!v?!!Wn(d,D(n,e,r,t)):!!Wn(d,A(Object.create(t),e))})),E(l,function(i,a){var f=o&&typeof i===Sn&&!r,p=y.indexOf(i),d=-1===p,v=!d&&f?p:a,w=m[v],_=a>=y.length,T=f&&d||!f&&!w;i=!r&&n.key?D(n,i,a):i,T?((w=new re(s,{parent:t,isLoop:!0,isAnonymous:g,tagName:u,root:e.cloneNode(g),item:i,index:a},e.innerHTML)).mount(),_?z.apply(w,[c||x,b]):P.apply(w,[x,m[a],b]),_||y.splice(a,0,i),m.splice(a,0,w),h&&le(t.tags,u,w,!0)):v!==a&&f&&(S(l,y[v])&&(B.apply(w,[x,m[a],b]),m.splice(a,0,m.splice(v,1)[0]),y.splice(a,0,y.splice(v,1)[0])),n.pos&&(w[n.pos]=a),!h&&w.tags&&U.call(w,a)),w.__.item=i,w.__.index=a,w.__.parent=t,T||w.update(i)}),M(l,m),y=l.slice(),x.insertBefore(c,f))},n.unmount=function(){E(m,function(e){e.unmount()})},n}function q(e,t,n){var r=this;T(e,function(t,i){var o,a,u,s=t.nodeType,c=i.parent;if(!n&&t===e)return{parent:c};if(3===s&&"STYLE"!==t.parentNode.tagName&&Wn.hasExpr(t.nodeValue)&&c.children.push({dom:t,expr:t.nodeValue}),1!==s)return i;var f="VIRTUAL"===t.tagName;if(o=x(t,xn))return f&&b(t,"loopVirtual",!0),c.children.push($(t,r,o)),!1;if(o=x(t,gn))return c.children.push(Object.create(Xn).init(t,r,o)),!1;if((a=x(t,vn))&&Wn.hasExpr(a))return c.children.push({isRtag:!0,expr:a,dom:t,attrs:[].slice.call(t.attributes)}),!1;if(u=ie(t),f&&(x(t,"virtualized")&&t.parentElement.removeChild(t),u||x(t,"virtualized")||x(t,"loopVirtual")||(u={tmpl:t.outerHTML})),u&&(t!==e||n)){if(!f||x(t,vn)){var p={root:t,parent:r,hasImpl:!0};return c.children.push(ue(u,p,t.innerHTML,r)),!1}b(t,"virtualized",!0);var l=new re({tmpl:t.outerHTML},{root:t,parent:r},t.innerHTML);c.children.push(l)}return V.apply(r,[t,t.attributes,function(e,t){t&&c.children.push(t)}]),{parent:c}},{parent:{children:t}})}function V(t,n,r){var i=this;E(n,function(n){if(!n)return!1;var o,a=n.name,u=e(a);S(yn,a)?o=Object.create(Yn).init(t,i,a,n.value):Wn.hasExpr(n.value)&&(o={dom:t,expr:n.value,attr:a,bool:u}),r(n,o)})}function H(e,t,n){var r="o"===n[0],i=r?"select>":"table>";if(e.innerHTML="<"+i+t.trim()+"t?-1:0}function Qe(e){return xr.groupBy(e.sort(),xr.isEqual)}function Xe(e){var t={};return e.map(function(e){t[e[0]]=e[1]}),t}function Ye(e,t){var n=xr.clone(e);return n.push.apply(n,t),n}function et(e){(e=xr.filter(e,function(e){return e.length>0})).sort(Ze);var t=e.reduce(function(e,t){return!t||t.length<1?"":e+"("+RegExp.escape(t)+")|"},""),n=new RegExp(t);return function(e){var t=n.exec(e);return!(xr.isNull(t)||!t[0])&&t[0]}}function tt(e){console.log("%j\n",e)}function nt(e){if(!e)return!1;var t=e.charCodeAt();return!isNaN(t)&&(4732}function ot(e){var t=e.charCodeAt();return!isNaN(t)&&t>=65&&t<=90}function at(e,t,n){var r=[],i=e[0].charCodeAt(),o=!1,a=0;for(43===i||45===i?(r.push(e[0]),e=e.substr(1),a++):46===i&&(e=e.substr(1),a++,t++,r.push("0"),r.push("."),o=!0);nt(e[0])&&0!==e.length;)r.push(e[0]),e=e.substr(1),t++,a++;if("."===e[0]&&nt(e[1])){for(r.push("."),r.push(e[1]),e=e.substr(2),t++,t++,a++,a++;nt(e[0])&&0!==e.length;)r.push(e[0]),e=e.substr(1),a++,t++;return[a,["float",parseFloat(r.join(""),10),t,n]]}return o?[a,["float",parseFloat(r.join(""),10),t,n]]:[a,["integer",parseInt(r.join(""),10),t,n]]}function ut(e,t,n,r){for(var i=[],o=0;!rt(e[0])&&it(e[0])&&!t(e);)i.push(e[0]),e=e.substr(1),o++,n++;return i=i.join(""),[[o,["identifier",i,n,r]]]}function st(e,t,n,r){var i=ut(e,t,n,r);return i[0][1][0]="constructor",i}function ct(e,t,n){var r=[],i=1,o=t;for(e=e.substr(1);34!==e[0].charCodeAt();)if(r.push(e[0]),e=e.substr(1),i++,o++,e.length<1)throw vr.JSyntaxError(n,t,"Error: missing quotation mark");return i++,[i,["stringlit",r.join(""),o,n]]}function ft(e,t,n){if(e.length<4)return!1;var r=e.substr(0,4);return"then"===r?["thenexp","then"]:"true"===r&&["truelit","true"]}function pt(e,t,n,r,i){var o=n.length;return!(e.length1&&At(r)&&n(At(r)))for(;n(jt(r))&&n(At(r))&&(u.push(e(r)),t(At(u).exprType));){if(!At(r))throw vr.JSyntaxError(o,i,"Unexpected end of source");if(At(r)[0],r.length<=1)break}if(!At(r))throw vr.JSyntaxError(At(r)[3],At(r)[2],"unexpected end of source");return n(At(r))&&u.push(e(r)),u}function Dt(e,t,n,r,i){var o,a,u=Xt(n);if(!e(u))throw vr.JSyntaxError(At(n)[2],At(n)[3],"Unexpected token: ``"+At(n)[0]+"''");if(o=[u],n.length>1&&At(n)[0]===t){for(;At(n)[0]===t;){if(n.pop(),a=Xt(n),!At(n))throw vr.JSyntaxError(At(n)[3],At(n)[2],"Missing terminator: "+t);o.push(a)}return o}return o}function Mt(e,t,n){var r;if("right_square"===At(e)[0]?r=[]:"comma"===At(e)[0]?(e.pop(),r=[]):r=Dt(function(e){return!0},"comma",e,At(e)[3],At(e)[2]),!At(e)||"right_square"!==At(e)[0])throw vr.JSyntaxError(At(e)[3],At(e)[2],"list must be terminated by ]");return e.pop(),Ot(new _r.ListT(r),e,t,n)}function Rt(e,t,n){var r,i,o=Xt(e);if("Name"!==o.exprType)throw vr.JSyntaxError(t,n,"Expected an identifier in function definition");if(r="right_paren"===At(e)[0]?[]:Ct(Xt,Jr,Wt,e,n,t),!e||"right_paren"!==At(e)[0])throw vr.JSyntaxError(t,n,"Formal parameters must be followed by )");return e.pop(),i=Xt(e),Ot(new _r.DefFunc(o,r,i),e,i.linenum,i.charnum)}function Ut(e,t,n){var r,i;if(At(e)||vr.JSyntaxError(t,n,"Unexpected end of source"),r=Ct(zt,jr,Ir,e,n,t),At(e)&&"right_brace"!==At(e)[0])throw vr.JSyntaxError(At(e)[2],At(e)[3],"let/def form must have a closing }");if(!At(e))throw vr.JSyntaxError(xr.last(r).linenum,xr.last(r).charnum,"Unexpected end of source");if(e.pop(),e.length<=0)throw vr.JSyntaxError(xr.last(r).linenum,xr.last(r).charnum,"let/def form must have a body");if("Definition"===(i=Xt(e)).exprType||"FunctionDefinition"===i.exprType)throw vr.JSyntaxError(i.linenum,i.charnum,"Body of a let/def expression cannot be a definition");return Ot(new _r.LetExp(r,i),e,i.linenum,i.charnum)}function Bt(e,t,n){var r,i,o=Xt(e);if("Name"!=o.exprType)throw vr.JSyntaxError(At(e)[3],At(e)[2],"Expected an identifier in function definition");if(r="right_paren"===At(e)[0]?[]:Ct(Xt,Jr,Wt,e,n,t),"right_paren"!==At(e)[0])throw vr.JSyntaxError(t,n,"Formal parameters must be followed by )");if(e.pop(),"->"!==At(e)[1])throw vr.JSyntaxError(At(e)[3],At(e)[2],"Function parameters in let/def form must be followed by ->");return e.pop(),i=Xt(e),Ot(new _r.DefFunc(o,r,i),e,i.linenum,i.charnum)}function Pt(e,t,n){var r,i=Xt(e);if("Name"!=i.exprType)throw vr.JSyntaxError(i.linenum,i.charnum,"Expected an identifier in let/def binding");if(!At(e)||"="!==At(e)[1])throw vr.JSyntaxError(i.linenum,i.charnum,"An identifier in a let/def binding must be followed by ``=''");if(e.pop(),!It(e,["comma","arrow","right_brace","right_square"],i.linenum,i.charnum))throw vr.JSyntaxError(i.linenum,i.charnum,"The binding of "+identifier.val+" must not be followed by "+At(e)[0]);if("Definition"===(r=Xt(e)).exprType||"FunctionDefinition"===r.exprType)throw vr.JSyntaxError(r.linenum,r.charnum,"A definition cannot be the value of a binding");return Ot(new _r.Def(i,r),e,r.linenum,r.charnum)}function zt(e){var t=At(e)[3],n=At(e)[2];return At(e)&&"left_paren"===At(e)[0]?(e.pop(),Bt(e,t,n)):Pt(e,t,n)}function $t(e,t,n){var r,i=Xt(e,t,n);if("TypeOperator"!==i.exprType)throw vr.JSyntaxError(i.linenum,i.charnum,"Expected a type operator in data type definition");if("right_paren"!==At(e)[0])o=Ct(Xt,Jr,Wt,e,n,t);else var o=[];if(!e||"right_paren"!==At(e)[0])throw vr.JSyntaxError(xr.last(o).linenum,xr.last(o).charnum,"Data type parameters must be followed by )");return e.pop(),r=Xt(e),Ot(new _r.DataType(i,o,r),e,r.linenum,r.charnum)}function qt(e,t,n){var r,i;if(e.length<2)throw vr.JSyntaxError(t,n,"Unexpected end of source");if("left_paren"===At(e)[0])return e.pop(),$t(e,t,n);if(It(e,["constructor"],t,n))throw vr.JSyntaxError(t,n,"deftype must be followed by a single constructor if it is not a data type definition with type variables");if(i=Xt(e,t,n),!e)throw vr.JSyntaxError(i.linenum,i.charnum,"Unexpected end of source");if("TypeOperator"!==i.exprType)throw vr.JSyntaxError(i.linenum,i.charnum,"left-hand side of type alias was not a type operator");if("Application"!==(r=Xt(e,t,n)).exprType&&"TypeOperator"!==r.exprType)throw vr.JSyntaxError(r.linenum,r.charnum,"was expecting an application or type operator on the right-hand side of a type alias");return Ot(new _r.DefType(i,r),e,r.linenum,r.charnum)}function Vt(e,t,n){var r,i;if(e.length<2)throw vr.JSyntaxError(t,n,"Unexpected end of source");if("left_paren"===At(e)[0])return e.pop(),Rt(e,t,n);if("left_brace"===At(e)[0])return e.pop(),Ut(e,At(e)[3],At(e)[2]);if(It(e,["identifier"],t,n))throw vr.JSyntaxError(t,n,"def must be followed by identifier, not "+At(e)[0]);if(r=Xt(e),!At(e))throw vr.JSyntaxError(r.linenum,r.charnum,"Unexpected end of source");if(!It(e,["comma","arrow","right_brace","right_square"],r.linenum,r.charnum))throw vr.JSyntaxError(r.linenum,r.charnum,"def "+r.val+" must not be followed by "+At(e)[0]);if("Definition"===(i=Xt(e)).exprType||"FunctionDefinition"===i.exprType)throw vr.JSyntaxError(i.linenum,i.charnum,"A definition cannot be the value of a binding");return Ot(new _r.Def(r,i),e,i.linenum,i.charnum)}function Ht(e,t,n){var r,i;if("integer"!==At(e)[0]||At(e)[1]<1)throw vr.JSyntaxError(t,n,"defop must be followed by integer precedence >= 1");if(e.pop(),"Left"!==At(e)[1]&&"Right"!==At(e)[1])throw vr.JSyntaxError(t,n,"defop must be followed by precedence and then either Left or Right");if(e.pop(),"left_paren"!==At(e)[0])throw vr.JSyntaxError(t,n,"defop arguments must start with (");if(e.pop(),!e.slice(e.length-3,e.length).every(function(e){return"identifier"===e[0]}))throw vr.JSyntaxError(t,n,"defop must be surrounded by exactly 3 identifiers");if(i=e.slice(e.length-3,e.length),e.pop(),e.pop(),e.pop(),"right_paren"!==At(e)[0])throw vr.JSyntaxError(t,n,"defop pattern must be terminated with )");return e.pop(),(r=[new _r.Name(i[1][1]),new _r.Name(i[0][1]),new _r.Name(i[2][1])]).map(function(e){return e.linenum=t,e.charnum=n,e}),Ot(new _r.DefFunc(r[0],r.slice(1,3),Xt(e)),e,xr.last(r).linenum,xr.last(r).charnum)}function Kt(e,t,n){var r,i,o;if(It(e,["def","comma","lambda"],t,n)){if(r=Xt(e),At(e)&&"thenexp"===At(e)[0]){if(e.pop(),i=Xt(e),At(e)&&"elsexp"===At(e)[0]){if(e.pop(),xr.size(e)<1)throw vr.JSyntaxError(i.linenum,i.charnum,"Unexpected end of source");return o=Xt(e),Ot(new _r.If(r,i,o),e,o.linenum,o.charnum)}throw vr.JSyntaxError(i.linenum,i.charnum,"If expression must include an else variant")}throw vr.JSyntaxError(r.linenum,r.charnum,"if ``exp'' must be folowed by ``then'' exp, not "+jt(e)[0])}throw vr.JSyntaxError(t,n,"``if'' cannot be followed by "+At(e)[0])}function Wt(e){return"identifier"===e[0]&&"->"!==e[1]}function Gt(e,t,n){var r=Ct(Xt,Jr,Wt,e,n,t);if("->"!==At(e)[1])throw vr.JSyntaxError(xr.last(r).linenum,xr.last(r).charnum,"arrow must follow parameters in lambda, not "+At(e)[0]);e.pop();var i=Xt(e);return Ot(new _r.FuncT(r,i),e,i.linenum,i.charnum)}function Zt(e,t,n){var r,i,o,a=Xt(e);if(!At(e))throw vr.JSyntaxError(a.linenum,a.charnum,"Unexpected end of source");if(r=At(e),_r.OPInfo[r[1]]){if(i=Qt(e,1,a,a.linenum,a.charnum),At(e)&&"right_paren"===At(e)[0])return e.pop(),i;throw vr.JSyntaxError(a.linenum,a.charnum,"Mismatched parentheses or missing parenthesis on right-hand side")}if(o="right_paren"!==At(e)[0]?Ct(Xt,Cr,Lr,e,At(e)[2],At(e)[3]):[],At(e)&&"right_paren"===At(e)[0])return e.pop(),Ot(_r.makeApp(a,o),e,n,t);throw vr.JSyntaxError(At(e)[3],At(e)[2],"Mismatched parentheses or missing parenthesis on right-hand side")}function Qt(e,t,n,r,i){for(n||(n=Xt(e));;){var o=At(e);if(!o)throw vr.JSyntaxError(r,i,"Unexpected end of source");var a=_r.OPInfo[o[1]];if(!a||a[0]0;)t=Ar.annotate_fvs(Or.desugar(Xt(e),r)),n.push(t);return{ast:n,types:r}}catch(e){void 0!==e.stxerror?(e.stxerror(),console.error("Tokenization error")):console.log(e.errormessage)}}function en(e,t){var n={};n.name=e,n.bindings={};for(var r=0;r=0&&/\s/.test(e[t]););return t}function t(t,u){var s=/.*/g,c=s.lastIndex=u++,f=s.exec(t)[0].match(o);if(f){var p=c+f[0].length,l=t[c=e(t,c)];if(c<0||~n.indexOf(l))return p;if("."===l)"."===t[c-1]&&(u=p);else if("+"===l||"-"===l)(t[--c]!==l||(c=e(t,c))<0||!a.test(t[c]))&&(u=p);else if(~i.indexOf(l)){for(var h=c+1;--c>=0&&a.test(t[c]););~r.indexOf(t.slice(c+1,h))&&(u=p)}}return u}var n="[{(,;:?=|&!^~>%*/",r=["case","default","do","else","in","instanceof","prefix","return","typeof","void","yield"],i=r.reduce(function(e,t){return e+t.slice(-1)},""),o=/^\/(?=[^*>/])[^[/\\]*(?:(?:\\.|\[(?:\\.|[^\]\\]*)*\])[^[\\/]*)*?\/[gimuy]*/,a=/[$\w]/;return t}(),Kn=function(e){function t(e){return e}function n(e,t){return t||(t=b),new RegExp(e.source.replace(/{/g,t[2]).replace(/}/g,t[3]),e.global?c:"")}function r(e){if(e===v)return g;var t=e.split(" ");if(2!==t.length||h.test(e))throw new Error('Unsupported brackets "'+e+'"');return t=t.concat(e.replace(d,"\\").split(" ")),t[4]=n(t[1].length>1?/{[\S\s]*?}/:g[4],t),t[5]=n(e.length>3?/\\({|})/g:g[5],t),t[6]=n(g[6],t),t[7]=RegExp("\\\\("+t[3]+")|([[({])|("+t[3]+")|"+m,c),t[8]=e,t}function i(e){return e instanceof RegExp?u(e):b[e]}function o(e){(e||(e=v))!==b[8]&&(b=r(e),u=e===v?t:n,b[9]=u(g[9])),x=e}function a(e){var t;t=(e=e||{}).brackets,Object.defineProperty(e,"brackets",{set:o,get:function(){return x},enumerable:!0}),s=e,o(t)}var u,s,c="g",f=/\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,p=/"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|`[^`\\]*(?:\\[\S\s][^`\\]*)*`/g,l=p.source+"|"+/(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source+"|"+/\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?([^<]\/)[gim]*/.source,h=RegExp("[\\x00-\\x1F<>a-zA-Z0-9'\",;\\\\]"),d=/(?=[[\]()*+?.^$|])/g,m=p.source+"|"+/(\/)(?![*\/])/.source,y={"(":RegExp("([()])|"+m,c),"[":RegExp("([[\\]])|"+m,c),"{":RegExp("([{}])|"+m,c)},v="{ }",g=["{","}","{","}",/{[^}]*}/,/\\([{}])/g,/\\({)|{/g,RegExp("\\\\(})|([[({])|(})|"+m,c),v,/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/,/(^|[^\\]){=[\S\s]*?}/],x=void 0,b=[];return i.split=function(e,t,n){function r(e){d&&(e=d+e,d=""),t||a?p.push(e&&e.replace(n[5],"$1")):p.push(e)}function i(n,r,i){return i&&(r=Hn(e,n)),t&&r>n+2&&(c="⁗"+h.length+"~",h.push(e.slice(n,r)),d+=e.slice(u,n)+c,u=r),r}n||(n=b);var o,a,u,s,c,f,p=[],l=n[6],h=[],d="";for(a=u=l.lastIndex=0;o=l.exec(e);){if(f=l.lastIndex,s=o.index,a){if(o[2]){var m=o[2],v=y[m],g=1;for(v.lastIndex=f;o=v.exec(e);)if(o[1]){if(o[1]===m)++g;else if(!--g)break}else v.lastIndex=i(o.index,v.lastIndex,o[2]);l.lastIndex=g?e.length:v.lastIndex;continue}if(!o[3]){l.lastIndex=i(s,f,o[4]);continue}}o[1]||(r(e.slice(u,s)),u=l.lastIndex,(l=n[6+(a^=1)]).lastIndex=u)}return e&&u %s",t.riotData.tagName||"Unknown tag",this.tmpl),console.log(this.data))}function n(e){var t=r(e);return"try{return "!==t.slice(0,11)&&(t="return "+t),new Function("E",t+";")}function r(e){var t,n=Kn.split(e.replace(u,'"'),1),r=n.qblocks;if(n.length>2||n[0]){var o,a,c=[];for(o=a=0;o1?"["+i.join(",")+'].join(" ").trim()':i[0]:o(e,t)}return e}function o(e,t,n){var r;return e=e.replace(l,function(e,t,n,i,o){return n&&(i=r?0:i+e.length,"this"!==n&&"global"!==n&&"window"!==n?(e=t+'("'+n+p+n,i&&(r="."===(o=o[i])||"("===o||"["===o)):i&&(r=!h.test(o.slice(i)))),e}),r&&(e="try{return "+e+"}catch(e){E(e,this)}"),n?e=(r?"function(){"+e+"}.call(this)":"("+e+")")+'?"'+n+'":""':t&&(e="function(v){"+(r?e.replace("return ","v="):"v=("+e+")")+';return v||v===0?v:""}.call(this)'),e}var a={};e.hasExpr=Kn.hasExpr,e.loopKeys=Kn.loopKeys,e.clearCache=function(){a={}},e.errorHandler=null;var u=/\u2057/g,s=/\u2057(\d+)~/g,c=/^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/,f={"(":/[()]/g,"[":/[[\]]/g,"{":/[{}]/g},p='"in this?this:'+("object"!=typeof window?"global":"window")+").",l=/[,{][\$\w]+(?=:)|(^ *|[^$\w\.{])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g,h=/^(?=(\.[$\w]+))\1(?:[^.[(]|$)/;return e.version=Kn.version="v3.0.8",e}(),Gn=function(e){e=e||{};var t={},n=Array.prototype.slice;return Object.defineProperties(e,{on:{value:function(n,r){return"function"==typeof r&&(t[n]=t[n]||[]).push(r),e},enumerable:!1,writable:!1,configurable:!1},off:{value:function(n,r){if("*"!=n||r)if(r)for(var i,o=t[n],a=0;i=o&&o[a];++a)i==r&&o.splice(a--,1);else delete t[n];else t={};return e},enumerable:!1,writable:!1,configurable:!1},one:{value:function(t,n){function r(){e.off(t,r),n.apply(e,arguments)}return e.on(t,r)},enumerable:!1,writable:!1,configurable:!1},trigger:{value:function(r){var i,o,a,u=arguments,s=arguments.length-1,c=new Array(s);for(a=0;a|>([\S\s]*?)<\/yield\s*>|>)/gi,nr=/]*)['"]\s*>([\S\s]*?)<\/yield\s*>/gi,rr=/|>([\S\s]*?)<\/yield\s*>)/gi,ir={tr:"tbody",th:"tr",td:"tr",col:"colgroup"},or=Un&&Un<10?Jn:Fn,ar="div",ur="svg",sr={},cr=sr[dn]={},fr=0,pr=Object.freeze({Tag:G,tag:Z,tag2:Q,mount:X,mixin:Y,update:ee,unregister:te,version:"WIP"}),lr=0,hr=Object.freeze({getTag:ie,inheritFrom:oe,moveChildTag:ae,initChildTag:ue,getImmediateCustomParentTag:se,unmountAll:ce,getTagName:fe,cleanUpData:pe,arrayishAdd:le,arrayishRemove:he,mountTo:de,makeReplaceVirtual:me,makeVirtual:ye,moveVirtual:ve,selectTags:ge}),dr=Qn,mr={tmpl:Wn,brackets:Kn,styleManager:Vn,vdom:ln,styleNode:Vn.styleNode,dom:Pn,check:Bn,misc:Zn,tags:hr},yr=A({},pr,{observable:Gn,settings:dr,util:mr}),vr={JSyntaxError:xe,JTypeError:be,JInternalError:we},gr="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},xr=function(e,t){return t={exports:{}},e(t,t.exports),t.exports}(function(e,t){(function(){function n(e){function t(t,n,r,i,o,a){for(;o>=0&&o0?0:u-1;return arguments.length<3&&(i=n[a?a[s]:s],s+=e),t(n,r,i,a,s,u)}}function r(e){return function(t,n,r){n=_(n,r);for(var i=N(t),o=e>0?0:i-1;o>=0&&o0?a=o>=0?o:Math.max(o+u,a):u=o>=0?Math.min(o+1,u):o+u+1;else if(n&&o&&u)return o=n(r,i),r[o]===i?o:-1;if(i!==i)return o=t(l.call(r,a,u),b.isNaN),o>=0?o+a:-1;for(o=e>0?a:u-1;o>=0&&o=0&&t<=k};b.each=b.forEach=function(e,t,n){t=w(t,n);var r,i;if(O(e))for(r=0,i=e.length;r=0},b.invoke=function(e,t){var n=l.call(arguments,2),r=b.isFunction(t);return b.map(e,function(e){var i=r?t:e[t];return null==i?i:i.apply(e,n)})},b.pluck=function(e,t){return b.map(e,b.property(t))},b.where=function(e,t){return b.filter(e,b.matcher(t))},b.findWhere=function(e,t){return b.find(e,b.matcher(t))},b.max=function(e,t,n){var r,i,o=-1/0,a=-1/0;if(null==t&&null!=e)for(var u=0,s=(e=O(e)?e:b.values(e)).length;uo&&(o=r);else t=_(t,n),b.each(e,function(e,n,r){((i=t(e,n,r))>a||i===-1/0&&o===-1/0)&&(o=e,a=i)});return o},b.min=function(e,t,n){var r,i,o=1/0,a=1/0;if(null==t&&null!=e)for(var u=0,s=(e=O(e)?e:b.values(e)).length;ur||void 0===n)return 1;if(nt?(a&&(clearTimeout(a),a=null),u=c,o=e.apply(r,i),a||(r=i=null)):a||!1===n.trailing||(a=setTimeout(s,f)),o}},b.debounce=function(e,t,n){var r,i,o,a,u,s=function(){var c=b.now()-a;c=0?r=setTimeout(s,t-c):(r=null,n||(u=e.apply(o,i),r||(o=i=null)))};return function(){o=this,i=arguments,a=b.now();var c=n&&!r;return r||(r=setTimeout(s,t)),c&&(u=e.apply(o,i),o=i=null),u}},b.wrap=function(e,t){return b.partial(t,e)},b.negate=function(e){return function(){return!e.apply(this,arguments)}},b.compose=function(){var e=arguments,t=e.length-1;return function(){for(var n=this,r=t,i=e[t].apply(this,arguments);r--;)i=e[r].call(n,i);return i}},b.after=function(e,t){return function(){if(--e<1)return t.apply(this,arguments)}},b.before=function(e,t){var n;return function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=null),n}},b.once=b.partial(b.before,2);var J=!{toString:null}.propertyIsEnumerable("toString"),F=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];b.keys=function(e){if(!b.isObject(e))return[];if(y)return y(e);var t=[];for(var n in e)b.has(e,n)&&t.push(n);return J&&o(e,t),t},b.allKeys=function(e){if(!b.isObject(e))return[];var t=[];for(var n in e)t.push(n);return J&&o(e,t),t},b.values=function(e){for(var t=b.keys(e),n=t.length,r=Array(n),i=0;i":">",'"':""","'":"'","`":"`"},D=b.invert(C),M=function(e){var t=function(t){return e[t]},n="(?:"+b.keys(e).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(e){return e=null==e?"":""+e,r.test(e)?e.replace(i,t):e}};b.escape=M(C),b.unescape=M(D),b.result=function(e,t,n){var r=null==e?void 0:e[t];return void 0===r&&(r=n),b.isFunction(r)?r.call(e):r};var R=0;b.uniqueId=function(e){var t=++R+"";return e?e+t:t},b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var U=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},P=/\\|'|\r|\n|\u2028|\u2029/g,z=function(e){return"\\"+B[e]};b.template=function(e,t,n){!t&&n&&(t=n),t=b.defaults({},t,b.templateSettings);var r=RegExp([(t.escape||U).source,(t.interpolate||U).source,(t.evaluate||U).source].join("|")+"|$","g"),i=0,o="__p+='";e.replace(r,function(t,n,r,a,u){return o+=e.slice(i,u).replace(P,z),i=u+t.length,n?o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?o+="'+\n((__t=("+r+"))==null?'':__t)+\n'":a&&(o+="';\n"+a+"\n__p+='"),t}),o+="';\n",t.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{var a=new Function(t.variable||"obj","_",o)}catch(e){throw e.source=o,e}var u=function(e){return a.call(this,e,b)},s=t.variable||"obj";return u.source="function("+s+"){\n"+o+"}",u},b.chain=function(e){var t=b(e);return t._chain=!0,t};var $=function(e,t){return e._chain?b(t).chain():t};b.mixin=function(e){b.each(b.functions(e),function(t){var n=b[t]=e[t];b.prototype[t]=function(){var e=[this._wrapped];return p.apply(e,arguments),$(this,n.apply(b,e))}})},b.mixin(b),b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=s[e];b.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),"shift"!==e&&"splice"!==e||0!==n.length||delete n[0],$(this,n)}}),b.each(["concat","join","slice"],function(e){var t=s[e];b.prototype[e]=function(){return $(this,t.apply(this._wrapped,arguments))}}),b.prototype.value=function(){return this._wrapped},b.prototype.valueOf=b.prototype.toJSON=b.prototype.value,b.prototype.toString=function(){return""+this._wrapped}}).call(gr)}),br={display:function(){return this.exprType+" "+this.val},type:function(){return this.exprType},linenum:0,charnum:0},wr={unify:function(e){if(this.expr===e.expr)return e.expr;console.log("Could not unify "+this.expr+" with "+e.expr)},isTypeExpr:!0,linenum:0,charnum:0};Se.prototype=br,ke.prototype=br,Ne.prototype=br,Oe.prototype=br,Ae.prototype=br,je.prototype=br,Ie.prototype=br,Je.prototype=br,Fe.prototype=br,Le.prototype=br,Ce.prototype=br,De.prototype=br,Me.prototype=br,Re.prototype=br,Ue.prototype=br,Be.prototype=wr,Pe.prototype=wr,$e.prototype=wr,qe.prototype=br;var _r={IntT:Ne,FloatT:Oe,StrT:Ae,BoolT:je,ListT:Ie,FuncT:Fe,App:Ce,Name:De,Def:Me,OpT:Le,OPInfo:{"::":[2,"Left"],",":[1,"Left"],"->":[1,"Right"]},makeApp:Ke,If:Ue,DefFunc:Re,UnaryOp:ke,Nil:Je,LetExp:Se,gensym:function(){var e=0;return function(){var t="G"+e;return e+=1,t}}(),TypeVar:Be,TypeOp:Pe,TypeDecl:$e,Closure:Ee,isTypeExpr:Te,DefType:qe,DataType:He};RegExp.escape=function(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")};var Tr={not:Ge,groupOps:Qe,opMatch:et,dict:Xe,extend:Ye,empty:We,debugPrint:tt},Er={src:"\n;; This file declares the various types used by intrinsic/prelude definitions\n;; It is sort of special in that it doesn't care whether there are any associated definitions\n;; just that there are type definitions for that particular binding's name\n"},Sr=Object.keys(_r.OPInfo),kr=["defop","integer","constructor","left_paren","identifier","identifier","identifier","right_paren"],Nr={tokenize:mt,isIdentifier:it},Or={desugar:Tt},Ar=(xr.compose(Tr.not,xr.partial(xr.equal,[])),{annotate_fvs:kt}),jr=Jt(["Definition","FunctionDefinition"].map(Lt)),Ir=xr.compose(Tr.not,Jt(["right_brace"].map(Ft))),Jr=Jt(["Name"].map(Lt)),Fr=["def","comma","right_paren","right_square","right_brace","left_brace","right_brace"].map(Ft),Lr=xr.compose(Tr.not,Jt(Fr)),Cr=xr.compose(Tr.not,Jt(["Definition"].map(Lt))),Dr={parse:function(e){return Yt(Nr.tokenize(e))},tokenize:Nr.tokenize,parseFull:Yt},Mr={lookup:tn,makeEnv:en}.makeEnv("toplevel",[["len",function(e){return e.length}],["+",function(e){return function(t){return e+t}}],["*",function(e){return function(t){return e*t}}],["-",function(e){return function(t){return e-t}}],["/",function(e){return function(t){return e/t}}],[":",nn],["a",2],["b",3]]),Rr={evaluateString:on};yr.tag2("test",'

{output}

',"","",function(e){var t=this;t.output="",this.evaluate=function(){var e=this.refs.input;t.update({output:JSON.stringify(Rr.evaluateString(e.value))})}.bind(this)}),yr.mount("test")}(); diff --git a/server/desugar.js b/server/desugar.js index 43b590d..9ee46a9 100644 --- a/server/desugar.js +++ b/server/desugar.js @@ -21,7 +21,7 @@ function desugarList(lst) { else { var x = desugar(lst.xs[0]); var rest = lst.xs.slice(1); - return new typ.App(new typ.App(new typ.Name("(:)"), x), desugarList(new typ.ListT(rest))); + return new typ.App(new typ.App(new typ.Name(":"), x), desugarList(new typ.ListT(rest))); } } @@ -108,7 +108,7 @@ function desugar(stx, typeEnv) { return sugarTypeDecl(stx); } - if ((stx.func.ident === "-") && + if ((stx.func.ident === "-" || stx.func.ident == "+") && stx.p && isAtomicNumber(stx.p)) { console.log("Matched unary"); console.log(stx); diff --git a/server/package.json b/server/package.json index 8f560ab..17be56f 100644 --- a/server/package.json +++ b/server/package.json @@ -17,6 +17,7 @@ "rollup-plugin-commonjs": "^8.0.2", "rollup-plugin-node-resolve": "^3.0.0", "rollup-plugin-riot": "^1.1.0", + "rollup-plugin-uglify": "^2.0.1", "serve-favicon": "~2.4.2" }, "devDependencies": { diff --git a/server/prelude.js b/server/prelude.js index a77ce0b..ec53b84 100644 --- a/server/prelude.js +++ b/server/prelude.js @@ -2,121 +2,7 @@ var src = ` ;; This file declares the various types used by intrinsic/prelude definitions ;; It is sort of special in that it doesn't care whether there are any associated definitions ;; just that there are type definitions for that particular binding's name - - -;; Type definitions -deftype String (Vector Char) - -deftype (Int) Intrinsic - -deftype (Float) Intrinsic - -deftype (Char) Intrinsic - -deftype (Byte) Intrinsic - -deftype (Void) Intrinsic - -deftype (IO a) Intrinsic - -deftype (Vector a) Intrinsic - -deftype (List a) - (Empty | - (Cons a (List a))) - -deftype (Bottom) - Undefined - -deftype (Maybe a) - (Nothing | - (Just a)) - -deftype (Either a b) - ((Left a) | - (Right b)) - -;; List functions - -(: :: (a -> (List a) -> (List a))) - -(map :: ((a -> b) -> (List a) -> (List b))) - -(head :: ((List a) -> a)) - -(tail :: ((List a) -> (List a))) - -(!! :: (Int -> (List a) -> a)) - -(take :: (Int -> (List a) -> (Maybe (List a)))) - -(drop :: (Int -> (List a) -> (Maybe (List a)))) - -;; Optional functions - -(maybe :: (b -> (a -> b) -> (Maybe a) -> b)) - -(either :: ((b -> c) -> (b -> c) -> (Either a b) -> c)) - -;; I/O functions - -(print :: (String -> (IO Void))) - -;; Operator definitions - -defop 1 Left (a + b) - (add a b) - -defop 1 Left (a - b) - (minus a b) - -defop 2 Left (a * b) - (mul a b) - -defop 2 Left (a / b) - (div a b) - -defop 2 Right (a ^ b) - (pow a b) - -defop 3 Left (a ++ b) - (listConcat a b) - -defop 3 Left (a == b) - (eq a b) - -defop 3 Left (a > b) - (gt a b) - -defop 3 Left (a >= b) - (gte a b) - -defop 3 Left (a < b) - (lt a b) - -defop 3 Left (a <= b) - (lte a b) - -defop 3 Left (a && b) - (and a b) - -defop 3 Left (a || b) - (or a b) - -defop 4 Left (x : xs) - (cons x xs) - -defop 5 Left (f $ x) - (fapply f x) - -defop 5 Left (f . g) - (compose f g) - -defop 3 Left (a | b) - (bitwiseOr a b) - -defop 3 Left (a & b) - (bitwiseAnd a b)`; +`; export default { "src" : src diff --git a/server/rollup.config.js b/server/rollup.config.js index 7aa1000..da74e26 100644 --- a/server/rollup.config.js +++ b/server/rollup.config.js @@ -2,6 +2,7 @@ import riot from 'rollup-plugin-riot' import nodeResolve from 'rollup-plugin-node-resolve' import commonjs from 'rollup-plugin-commonjs' import buble from 'rollup-plugin-buble' +import uglify from 'rollup-plugin-uglify' export default { entry: './tags/jlambda.js', @@ -13,7 +14,8 @@ export default { commonjs({ './vm.js' : ['evaluateString'] }), - buble() + buble(), + uglify() ], format: 'iife' } diff --git a/server/routes/.index.js.swp b/server/routes/.index.js.swp deleted file mode 100644 index 7561f3aee04eb2810be553b1da10285347c5041c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI&K}#D!6bJC9ry^)Wz4Z8u(A`M7tM-x_Jc?B8rL=+<%f>uoG|6seXEh?VpQL*3 zhp1BM!B62wDSfl9AYx4Dt>r)PnC#n`H#0xTA!HhhTkqa;Em$ONC8FzZZ?{`Ne^cot z(Xpg1JF=xVGKV8a5uItlaAPy-HkwhGia8P!nmDtXZTFfo2oA2 z*R^SSv%Hjl)#uA|Jp1C){So*K0SG_<0uX=z1Rwwb2>j;)HkqKWddA7(oKrr=Z&Na{=009U<00Izz00bZa0SG_<0)Hvcjhk6V0vRN+u_>=|eqY?w ziM~|o^z>V1BWYknua+C%%Ws%_RUR^DNV-_)@lvO3+qNSs?5zzFT`Se{dYwJV>P$O=Hzn{nW&o|LHa?Ss?+Uhf|gj{3w8Eh*4wr1xaS+`SKaoj+>?Q=@F|50 yyuS94_v5Z`6161Yg^4-n^x|*E; diff --git a/server/tags/.jlambda.js.swp b/server/tags/.jlambda.js.swp deleted file mode 100644 index 73637118dad22e5db99b566567b27d1e6bb9f95c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI&O-jQ+6bJBEaVr+xxE$jmx^Pl;Q|SRju`5w+G)z5YIox;y zy@af#a9yjPt&bU;abGgcmZ@FqBK>z{}fB*y_009U< z00Izz00bcL2L((@biYdUEK&ad|N8!am-d^)Yc=*L`9Z=<1PK%fKmY;|fB*y_009U< z00Izz00e#rgy4b{m$CL)G2-orZO+k7M{e1>QJPJ)otR-^*q(9idG6QsoF8X_RjiY8 W3oRGy;|^7wY7hz^X)R^J?swcUTSis(!l20wr4xZc!(Gd49gV7=o4HjaIn{YMX!KmY>o75GHU zON;qO{i`>pW~MjZ+X(w0009U<00Izz00bZafiV=|q(J9#?+?Sf&kmo3f1blvJRkr8 z2tWV=5P$##AOHafKmY;|7()TwB)Xa+dXi+n|Bt@^KYu3rD|wXkBoC51$&KV%aw)lx zoJh1}OHz}3lT1n`Bp)UHQSULd!IdEZ0SG_<0uX=z1Rwwb2tZ(L1wt9}ck?WcS11fz z!$yhB=#-SwEn~Tq#=c2)tE<`6*hcN0Qq)em>}PAHT&_rAs;$ZwRaNnBwq9oOCR!G*;WT6RUaO59EM7H(#Of^>C%apx$Nfv{$6NQme!BRmAywr`>2p sjs5EJsP}1B7Y?>$vmifvu$hk%Q}x&!vNu?e%T>L+z{_g$8HEFZ7cr}Twg3PC diff --git a/server/tags/test.tag b/server/tags/test.tag index eca23a3..271e156 100644 --- a/server/tags/test.tag +++ b/server/tags/test.tag @@ -1,19 +1,25 @@ - - + +

+ {output} +

diff --git a/server/views/.index.pug.swp b/server/views/.index.pug.swp deleted file mode 100644 index d151d6f2671e880ea9f813ae3e1b7ddcfa5ed9e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI%O-jR15C`z7D>q`%jmxK9L_wQYHx=mt6uVS$`I0;}ZJLC z!~=K&y?{6=b>pV(viN^64D&J>UVe~8h*vv5ZmCAKMzYF8Zx4r;&#&K9-XQ85TkK9< zmUY&d+C?;yf$qtv?s|cCt;u>Ob9|M&a$0iz8hB;Ci0W6QJlyH4mmQ#{!P89#szs%;&+sv#B5?Fl0%p{uqx6+ GnL= 1.0.0" +commander@~2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1434,6 +1440,12 @@ rollup-plugin-riot@^1.1.0: riot-compiler "^3.0.0" rollup-pluginutils "^1.5.2" +rollup-plugin-uglify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-2.0.1.tgz#67b37ad1efdafbd83af4c36b40c189ee4866c969" + dependencies: + uglify-js "^3.0.9" + rollup-pluginutils@^1.5.0, rollup-pluginutils@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" @@ -1666,6 +1678,13 @@ uglify-js@^2.6.1: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.9: + version "3.0.15" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.0.15.tgz#aacb323a846b234602270dead8a32441a8806f42" + dependencies: + commander "~2.9.0" + source-map "~0.5.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" diff --git a/test.js b/test.js deleted file mode 100755 index 3507792..0000000 --- a/test.js +++ /dev/null @@ -1,149 +0,0 @@ -#! /usr/bin/node - -var parser = require("./parse.js"); -var cexps = require("./cexps.js"); -var closures = require("./closure_conversion.js"); -var desugar = require("./desugar.js"); -var environments = require("./environments.js"); -var errors = require("./errors.js"); -var tokens = require("./tokenize.js"); -var tools = require("./tools.js"); -var typecheck = require("./typecheck.js"); -var representation = require("./representation.js"); -var _ = require("underscore"); - -var qc = require("quickcheck"); -var assert = require("assert"); - - -/* my own generators */ - -function arbChars(n, max, min) { - return function () { - return _.invoke(_.times(_.random(1, n), - _.partial(arbChar, max, min)), - "call"); - }; -} - -function arbChar(max, min) { - return function() { - return String.fromCharCode(_.random(max, min)); - }; -} - -function arbCharRanges(ranges, max) { - return function() { - return _.flatten( - _.shuffle( - _.map(ranges, - function(bound) { - return _.sample(arbChars(max, bound[0], bound[1])(), - bound[1] - bound[0]); - }))).join(""); - }; -} - - -var arbName = arbCharRanges([[33, 33], - [35, 39], - [42,43], - [45, 122], - [124, 126]], - 200); - -var arbCapital = arbChar(65, 90); - -function arbArray(gen) { - return qc.arbArray(gen); -} - -function arbStrings() { - return qc.arbArray(qc.arbString); -} - - -function arbPair(gen) { - return function() { - return [gen(), gen()]; - }; -} - -function arbArrayofPairs() { - return arbArray(function() { - return arbArray(arbPair(qc.arbString)); - }); -} - -function arbPairs() { - return arbArray(arbPair(qc.arbString)); -} - - -/* Tests for misc tools */ -function emptyProp(xs) { - return (tools.empty(xs) === tools.empty(xs) && - ((tools.empty(xs) === true) || - (tools.empty(xs) === false))); -} - - -function dictProp(pairs) { - var dict = tools.dict(pairs); - var result = _.map(pairs, - function(pair) { - if ((_.size(pair) < 2) || - (_.size(pair[0]) < 1) || - (_.size(pair[1]) < 1)) { - return true; - } - return dict[pair[0]] === pair[1]; - }); - if (_.every(result, _.identity)) { - return true; - } - return false; -} - -function opMatchProp(strings) { - var match = tools.opMatch(strings); - var result = _.every(_.map(strings, - function (str) { - if (str.replace(/ /g,'').length < 1) { - return true; - } - var res = match(str); - if (res !== false) { - console.log(str); - return true; - } - return false; - }), - _.identity); - return result; -} - -function extendProp(pair) { - if (pair.length < 2) { - // empty lists or lists with one item are undefined - // so just return true because extend can't handle them - return true; - } - var x = _.first(pair); - var y = _.first(_.rest(pair)); - var extended = tools.extend(x,y); - return x.length + y.length === extended.length; -} - -/* Tokenizer tests */ - - -function toolsTests() { - assert.equal(true, tools.empty([])); - assert.equal(true, qc.forAll(dictProp, arbArrayofPairs)); - assert.equal(true, qc.forAll(extendProp, arbPairs)); - //assert.equal(true, qc.forAll(opMatchProp, arbStrings)); -} - -console.log(arbName()); -//toolsTests(); diff --git a/tokenize.js b/tokenize.js deleted file mode 100755 index cbe748a..0000000 --- a/tokenize.js +++ /dev/null @@ -1,432 +0,0 @@ -#! /usr/bin/node - -var fs = require("fs"); -var rep = require("./representation.js"); -var $ = require("./tools.js"); -var error = require("./errors.js"); -var operators = Object.keys(rep.OPInfo); -var _ = require("underscore"); - -function isDigit(c) { - if (!c) - return false; - var code = c.charCodeAt(); - if (isNaN(code)) { - return false; - } - return (47 < code) && (code < 58) -} - -function isWhitespace(c) { - if (!c) - return true; - - var code = c.charCodeAt(); - if (isNaN(code)) { - return true; - } - return (code === 9 || - code === 32 || - code === 10 || - code === 13 || - code === 11); -} - -function isIdentifier(c) { - var code = c.charCodeAt(); - return (!isNaN(code) && - code !== 41 && - code !== 40 && - code !== 125 && - code !== 123 && - code !== 93 && - code !== 91 && - code !== 44 && - code !== 34 && - code > 32); -} - -function isUpper(c) { - var code = c.charCodeAt(); - return (!isNaN(code) && - (code >= 65) && - (code <= 90)); -} - -function tokenizeNum(tokstream, charnum, linenum) { - var number = []; - var code = tokstream[0].charCodeAt(); - var isFloat = false; - var n = 0; - // + - - // might want to remove this since it probably won't ever get run? - if (code === 43 || code === 45) { // + or - - number.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - } - else if (code === 46) { // . - tokstream = tokstream.substr(1); - n++; - charnum++; - number.push('0'); - number.push('.'); - isFloat = true; - } - - while (isDigit(tokstream[0]) && tokstream.length !== 0) { - number.push(tokstream[0]); - tokstream = tokstream.substr(1); - charnum++; - n++; - } - if (tokstream[0] === '.' && isDigit(tokstream[1])) { - number.push('.'); - number.push(tokstream[1]); - tokstream = tokstream.substr(2); - charnum++; charnum++; - n++; n++; - while (isDigit(tokstream[0]) && tokstream.length !== 0) { - number.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - charnum++; - } - return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]]; - } - if (!isFloat) - return [n, ["integer", parseInt(number.join(''), 10), charnum, linenum]]; - else - return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]]; -} - -/* Split up the tokenized identifier if an operator appears in it - * prefer longer identifiers that start with the same character(s) as shorter ones - * e.g. ++ over + - * Everything after the operator goes back on to the token stream - */ - -function tokenizeIdent(tokstream, - matchop, - charnum, - linenum) { - var identifier = []; - var n = 0; - while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) { - identifier.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - charnum++; - } - identifier = identifier.join(''); - - return [[n, ["identifier", identifier, charnum, linenum]]]; -} - -function tokenizeCtor(tokstream, - matchop, - charnum, - linenum) { - var ident = tokenizeIdent(tokstream, - matchop, - charnum, - linenum); - ident[0][1][0] = "constructor"; - return ident; -} - -function tokenizeStr(tokstream, charnum, linenum) { - var stringlit = []; - var n = 1; - var new_charnum = charnum; - tokstream = tokstream.substr(1); - while (tokstream[0].charCodeAt() !== 34) { - stringlit.push(tokstream[0]); - tokstream = tokstream.substr(1); - n++; - new_charnum++; - if (tokstream.length < 1) { - throw error.JSyntaxError(linenum, charnum, "Error: missing quotation mark"); - } - } - n++; - return [n, ["stringlit", stringlit.join(''), new_charnum, linenum]]; - -} - -function tokenizeT(tokstream, charnum, linenum) { - if (tokstream.length < 4) - return false; - var next4 = tokstream.substr(0,4); - if (next4 === "then") - return ["thenexp", "then"]; - else if (next4 === "true") - return ["truelit", "true"]; - return false; -} - -function peek(tokstream, toktype, word, charnum, linenum) { - var n = word.length; - if (tokstream.length < n) - return false; - var nextN = tokstream.substr(0, n); - if (nextN == word) { - return [toktype, word]; - } - return false; -} - - -function tokenize(tokstream, matchop) { - var tokens = []; - var charnum = 1; - var linenum = 1; - var i, result, lambda, num, comment; - - while (tokstream) { - switch (tokstream[0].charCodeAt()) { - /* falls through */ - case 59: // ; - while (tokstream[0].charCodeAt() !== 10) { - tokstream = tokstream.substr(1); - } - break; - case 9: // '\t' - charnum++; - tokens.push(["whitespace", '\t', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 32: // ' ' - charnum++; - tokens.push(["whitespace", ' ', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 10: // '\n' - linenum++; - charnum = 1; /* Reset the character number for each line to 1 */ - tokens.push(["whitespace", '\n', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 44: // ',' - charnum++; - tokens.push(["comma", ",", charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 40: // '(' - charnum++; - tokens.push(["left_paren", '(', charnum, linenum]); - tokstream = tokstream.substr(1); - - break; - /* falls through */ - case 41: // ')' - charnum++; - tokens.push(["right_paren", ')', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 123: // '{' - charnum++; - tokens.push(["left_brace", '{', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 125: // '}' - charnum++; - tokens.push(["right_brace", '}', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 91: // '[' - charnum++; - tokens.push(["left_square", '[', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 93: // ']' - charnum++; - tokens.push(["right_square", ']', charnum, linenum]); - tokstream = tokstream.substr(1); - break; - /* falls through */ - case 34: // '"' - result = tokenizeStr(tokstream, charnum, linenum); - var str = result[1]; - i = result[0]; - tokens.push(str); - tokstream = tokstream.substr(i); - break; - - /* falls through */ - case 46: // '.' - if (isDigit(tokstream[1])) { - result = tokenizeNum(tokstream, charnum, linenum); - num = result[1]; - i = result[0]; - if (!isNaN(num[1])) { - tokens.push(num); - } - tokstream = tokstream.substr(i); - break; - } - /* falls through */ - case 116: // 't' - result = tokenizeT(tokstream); - if (result) { - tokens.push($.extend(result, [charnum, linenum])); - tokstream = tokstream.substr(4); // 4 = length of either token - break; - } - /* falls through */ - case 105: // 'i' - var ifexp = peek(tokstream, "ifexp", "if"); - if (ifexp) { - tokens.push($.extend(ifexp, [charnum, linenum])); - tokstream = tokstream.substr(2); - break; - } - var inkeyword = peek(tokstream, "in", "in "); - if (inkeyword) { - tokens.push($.extend(inkeyword, [charnum, linenum])); - tokstream = tokstream.substr(3); - break; - } - - /* falls through */ - case 100: // 'd' - var defop = peek(tokstream, "defop", "defop"); - if (defop) { - tokens.push(["defop", "defop", charnum, linenum]); - tokstream = tokstream.substr(5); - break; - } - var deftype = peek(tokstream, "deftype", "deftype"); - if (deftype) { - tokens.push(["deftype", "deftype", charnum, linenum]); - tokstream = tokstream.substr(7); - break; - } - var def = peek(tokstream, "def", "def"); - if (def) { - tokens.push(["def", "def", charnum, linenum]); - tokstream = tokstream.substr(3); - break; - } - /* falls through */ - case 101: // e - result = peek(tokstream, "elsexp", "else"); - if (result) { - tokens.push($.extend(result, [charnum, linenum])); - tokstream = tokstream.substr(4); - break; - } - /* falls through */ - case 102: // f - result = peek(tokstream, "falselit", "false"); - if (result) { - tokens.push($.extend(result, [charnum, linenum])); - tokstream = tokstream.substr(5); - break; - } - /* falls through */ - case 108: // l - lambda = peek(tokstream, "lambda", "lambda"); - if (lambda) { - tokens.push($.extend(lambda, [charnum, linenum])); - tokstream = tokstream.substr(6); - break; - } - var letexp = peek(tokstream, "let", "let"); - if (letexp) { - tokens.push($.extend(letexp, [charnum, linenum])); - tokstream = tokstream.substr(3); - break; - } - - /* falls through */ - default: - if (isDigit(tokstream[0])) { - result = tokenizeNum(tokstream, charnum, linenum); - num = result[1]; - i = result[0]; - if (!isNaN(num[1])) { - tokens.push(num); - } - tokstream = tokstream.substr(i); - break; - } - var op = matchop(tokstream); - if (op) { - var l = op.length; - charnum = charnum + l; - tokstream = tokstream.substr(l); - tokens.push(["identifier", op, charnum, linenum]); - } - else { - if (isUpper(tokstream[0])) { - result = tokenizeCtor(tokstream, matchop, charnum, linenum); - } - else { - result = tokenizeIdent(tokstream, matchop, charnum, linenum); - } - for(var index = 0; index < result.length; index++) { - charnum++; - tokens.push(result[index][1]); - tokstream = tokstream.substr(result[index][0]); - } - } - } - } - return tokens; -} - -function tokenizeHelp(input, matchop, strip_whitespace) { - try { - return tokenize(input, matchop).reverse().filter(function(x) { - if (strip_whitespace) { - return x[0] !== "whitespace"; - } - else { - return true; - } - }); - } catch (e) { - console.log(e.stxerror()); - process.exit(1); - } -} - -var defop_pattern = ["defop", "integer", "constructor", - "left_paren", "identifier", - "identifier", "identifier", "right_paren"]; - -function checkPattern(x, i) { - return x === defop_pattern[i]; -} - -function tokenizeFull(input) { - var preludeSrc = fs.readFileSync("./prelude.jl"); - var matchop; - input = [preludeSrc, input].join(""); - var initialPass = tokenizeHelp(input, _.constant(false), true).reverse(); - - for (var i = 0; i < initialPass.length; i++) { - if (initialPass.slice(i, i+8). - map(_.first). - every(checkPattern)) { - rep.OPInfo[initialPass[i+5][1]] = - [parseInt(initialPass[i+1][1], 10), - initialPass[i+2][1]]; - } - } - operators = Object.keys(rep.OPInfo); - matchop = $.opMatch(operators); - return tokenizeHelp(input, matchop, true); -} - -module.exports = {tokenize : tokenizeFull, - isIdentifier : isIdentifier}; diff --git a/tools.js b/tools.js deleted file mode 100644 index b670441..0000000 --- a/tools.js +++ /dev/null @@ -1,104 +0,0 @@ -var _ = require("underscore"); - -function empty(xs) { - return _.size(xs) < 1; -} - -function not(x) { - return !x; -} - -function min(a, b) { - if (a < b) { - return 1; - } - else if (a > b) { - return -1; - } - else { - return 0; - } -} - -function max(a, b) { - if (a > b) { - return 1; - } - else if (a < b) { - return -1; - } - else { - return 0; - } -} - -function groupOps(ops) { - return _.groupBy(ops.sort(), _.isEqual); -} - -function find(f, haystack) { - for(var i = 0; i < haystack.length; i++) { - if (f(haystack[i])) { - return i; - } - } - return false; -} - -function dict(pairs) { - var o = {}; - pairs.map(function(p) { - o[p[0]] = p[1]; - }); - return o; -} - -function extend(xs, ys) { - var result = _.clone(xs); - result.push.apply(result, ys); - return result; -} - -RegExp.escape= function(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); -}; - -function operatorMatch(ops) { - ops = _.filter(ops, - function (op) { - return op.length > 0; - }); - ops.sort(min); - var rstring = ops.reduce( - function(acc, x) { - if (!x || x.length < 1) { - return ""; - } - return acc + "(" + RegExp.escape(x) + ")|"; - }, ""); - var reg = new RegExp(rstring); - return function(x) { - var matched = reg.exec(x); - if ((!(_.isNull(matched))) && matched[0]) { - return matched[0]; - } - else { - return false; - } - }; -} - -function debugPrint(stx) { - console.log("%j\n", stx); -} - - -module.exports = { - not : not, - groupOps : groupOps, - opMatch : operatorMatch, - dict: dict, - extend : extend, - empty : empty, - debugPrint : debugPrint -}; diff --git a/typecheck.js b/typecheck.js deleted file mode 100644 index c39306c..0000000 --- a/typecheck.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Typecheck an AST with a given environment - * the environment maps variables to types - * a variable can either be bound or free - * when we say a variable is free that means that it is either - * unbound (which causes an exception to be raised immediately) - * or it is bound in the outer scope - * - * So the AST must first be converted to a form where each function body is tied - * to an environment mapping identifiers to types - */ - -var rep = require("./representation.js"); -var env = require("./environments.js"); - -/* - * Map all bindings with explicit type annotations in the environment - */ diff --git a/vm.js b/vm.js deleted file mode 100755 index 0a1eafb..0000000 --- a/vm.js +++ /dev/null @@ -1,66 +0,0 @@ -#! /usr/bin/node - -var typ = require("./representation.js"); -var parse = require("./parse.js"); -var tokenizer = require("./tokenize.js"); -var pprint = require("./pprint.js"); -var env = require("./environments.js"); -var fs = require("fs"); - -var istr = fs.readFileSync('/dev/stdin').toString(); -var ast = parse.parseFull(tokenizer.tokenize(istr)); - -function apply(func, p) { - return func(p); -} - -function evaluateAll(ast, environment) { - var l = ast.length; - var evaled = []; - for (var i = 0; i < l; i++) { - // should look for closures? - evaled.push(evaluate(ast[i], environment)); - } - return evaled; -} - -function evaluate(ast, environment) { - if (ast.exprType == "Application") { - return apply(evaluate(ast.func, environment), evaluate(ast.p, environment)); - } - else if (ast.exprType === "Unary") { /* Unary function application */ - return apply(evaluate(ast.op, environment), evaluate(ast.val, environment)); - } - else if (ast.exprType === "Name") { - //console.log(env.lookup(ast.ident, environment)); - return env.lookup(ast.ident, environment); - } - else if (ast.exprType === "If") { - if (evaluate(ast.condition, environment)) { - return evaluate(ast.thenexp, environment); - } - else { - return evaluate(ast.elseexp, environment); - } - } - else if (ast.exprType === "Definition") { - console.log("XXX"); - console.log(ast); - } - else { - return ast.val; - } -} -var testenv = env.makeEnv("toplevel", - [ - ["+", function(a) { return function(b) { return a + b; } }], - ["*", function(a) { return function(b) { return a * b; } }], - ["a", 2], - ["b", 3]]); - -console.log(ast.types); -//var all = evaluate(ast, testenv); -//console.log(all); -//console.log("%j", testenv); -//console.log("%j", ast[0][ast[0].length - 1]); -//console.log("%j", ast[0][ast[0].length - 1]);