/
wisp.js.min
38 lines (38 loc) · 15.6 KB
/
wisp.js.min
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var wisp={};wisp.empty=[];wisp.isEmpty=function(a){return a instanceof Array&&a.length===0};wisp.isNumber=function(a){return typeof a==="number"};wisp.isString=function(a){return typeof a==="string"};wisp.isBoolean=function(a){return typeof a==="boolean"};wisp.isAbstractSyntax=function(a){return typeof a==="object"&&a.type};wisp.isAbstractNumber=function(a){return typeof a==="object"&&a.type&&a.type==="number"};wisp.isAbstractString=function(a){return typeof a==="object"&&a.type&&a.type==="string"};
wisp.isAbstractBoolean=function(a){return typeof a==="object"&&a.type&&a.type==="bool"};wisp.isAbstractIdentifier=function(a){return typeof a==="object"&&a.type&&a.type==="id"};wisp.isAbstractLambdaClosure=function(a){return typeof a==="object"&&a.type&&a.type==="lambdaClosure"};wisp.isAbstractMacroClosure=function(a){return typeof a==="object"&&a.type&&a.type==="macroClosure"};wisp.verifyNumber=function(a){wisp.isAbstractNumber(a)||wisp.verifyTypeError(a,"number");return a};
wisp.verifyString=function(a){wisp.isAbstractString(a)||wisp.verifyTypeError(a,"string");return a};wisp.verifyBoolean=function(a){wisp.isAbstractBoolean(a)||wisp.verifyTypeError(a,"boolean");return a};wisp.verifyIdentifier=function(a){wisp.isAbstractIdentifier(a)||wisp.verifyTypeError(a,"identifier",true);return a};wisp.verifyLambdaClosure=function(a){wisp.isAbstractLambdaClosure(a)||wisp.verifyTypeError(a,"lambda");return a};
wisp.verifyMacroClosure=function(a){wisp.isAbstractMacroClosure(a)||wisp.verifyTypeError(a,"macro");return a};wisp.verifyTypeError=function(a,b,c){c=c?"an":"a";wisp.exceptionHelper(a.toString()+" is not "+c+" "+b,[a])};wisp.isAtom=function(a){return wisp.isNumber(a)||wisp.isBoolean(a)||wisp.isString(a)};wisp.isNonEmptyCons=function(a){return a instanceof Array&&a.length===2};wisp.isCons=function(a){return wisp.isEmpty(a)||wisp.isNonEmptyCons(a)};
wisp.cons=function(a,b){wisp.isCons(b)||wisp.exceptionHelper("must cons onto another list",[a,b]);return[a,b]};wisp.first=function(a){wisp.isNonEmptyCons(a)||wisp.exceptionHelper("first is only defined for non-empty lists",[a]);return a[0]};wisp.rest=function(a){wisp.isNonEmptyCons(a)||wisp.exceptionHelper("rest is only defined for non-empty lists",[a]);return a[1]};wisp.second=function(a){return wisp.first(wisp.rest(a))};wisp.third=function(a){return wisp.first(wisp.rest(wisp.rest(a)))};
wisp.firsts=function(a){if(wisp.isEmpty(a))return a;return wisp.cons(wisp.first(wisp.first(a)),wisp.firsts(wisp.rest(a)))};wisp.seconds=function(a){if(wisp.isEmpty(a))return a;return wisp.cons(wisp.second(wisp.first(a)),wisp.seconds(wisp.rest(a)))};wisp.append=function(a,b){if(!wisp.isCons(a)||!wisp.isCons(b))wisp.exceptionHelper("Wisp error: both arguments to append must be lists",[a,b]);if(wisp.isEmpty(a))return b;return wisp.cons(wisp.first(a),wisp.append(wisp.rest(a),b))};
Array.prototype.toWispString=function(){return this._toWispString(true)};Array.prototype._toWispString=function(a){wisp.isCons(this)||wisp.exceptionHelper("toWispString only applies to Wisp lists",[this]);if(wisp.isEmpty(this))return"";var b,c="";b=wisp.first(this);if(a)c="(list ";c+=wisp.isCons(b)?b._toWispString(true):b.toString();b=wisp.rest(this)._toWispString(false);c+=b===""?"":" ";c+=b;if(a)c+=")";return c};Array.prototype.toString=Array.prototype.toWispString;
wisp.throwException=function(a){var b="Wisp Error: ";if(typeof a==="object"&&a.msg){b+=a.msg;if(a.lineNo)b+=" (near line "+a.lineNo+")"}else b+=a.toString();throw b;};wisp.exceptionHelper=function(a,b){for(var c={msg:a},d=0;d<b.length;d++)if(wisp.isAbstractSyntax(b[d])){c.lineNo=b[d].lineNo;break}wisp.throwException(c)};wisp.EOF={type:"EOF",toString:function(){return"End of File"}};wisp.EOL={type:"EOL",toString:function(){return"End of List"}};wisp.COMMENT={type:"Comment",toString:function(){return"Comment Line"}};
Array.prototype.toWispSexp=function(){var a,b,c,d=wisp.empty;c=this.reverse();for(a=0;a<c.length;a++){b=c[a];if(b instanceof Array)b=b.toWispSexp();d=wisp.cons(b,d)}return d};wisp.countOccurrence=function(a,b){var c=a.match(RegExp(b,"g"));if(c===null)return 0;return c.length};wisp.read=function(a,b){if(b===undefined)b={index:0,lineNo:1};var c=wisp._readIntoArray(a,b);return c instanceof Array?c.toWispSexp():c};
wisp._readIntoArray=function(a,b){if(a.length===0||a.length<=b.index)return wisp.EOF;var c,d;c=a.substring(b.index);var e=c.trim()[0],f=c.indexOf(e);b.lineNo+=wisp.countOccurrence(c.substring(0,f),"\n");d=b.lineNo;switch(e){case ")":b.index+=f+1;return wisp.EOL;case "(":b.index+=f+1;for(e=[];;){c=wisp._readIntoArray(a,b);if(c!==wisp.COMMENT){if(c===wisp.EOL)break;c===wisp.EOF&&wisp.throwException({msg:"Error: end of file reached without reaching end of list",lineNo:d});e.push(c)}}return e;case '"':d=
c.substring(f).search(/[^\\]"/)+f+2;c=c.substring(0,d).trim();b.index+=d;return wisp.tokenToAbstractSyntax(c);case "'":b.index+=f+1;c=wisp._readIntoArray(a,b);return[wisp.tokenToAbstractSyntax("quote",d),c];case "`":b.index+=f+1;c=wisp._readIntoArray(a,b);return[wisp.tokenToAbstractSyntax("backquote",d),c];case "~":if(c[f+1]=="@"){b.index+=f+2;c=wisp._readIntoArray(a,b);return[wisp.tokenToAbstractSyntax("unquote-splice",d),c]}b.index+=f+1;c=wisp._readIntoArray(a,b);return[wisp.tokenToAbstractSyntax("unquote",
d),c];case ";":d=c.search(/\n/)+1||a.length;b.index+=d;return wisp.COMMENT;default:e=c.indexOf(")");if(e===-1)e=Infinity;f=c.search(/\S\s/)+1;if(f===0)f=a.length-b.index;e=e<f?e:f;c=c.substring(0,e);b.lineNo+=wisp.countOccurrence(c,"\n");c=c.trim();b.index+=e;return wisp.tokenToAbstractSyntax(c,d)}};
wisp.tokenToAbstractSyntax=function(a,b){var c={};if(wisp.parseIsNumber(a)){c.type="number";c.lineNo=b;c.value=parseFloat(a);c.toString=function(){return this.value+"(line "+this.lineNo+")"}}else if(wisp.parseIsBoolean(a)){c.type="bool";c.lineNo=b;c.value=a==="true";c.toString=function(){return this.value+""}}else if(wisp.parseIsString(a)){c.type="string";c.lineNo=b;c.value=a.substring(1,a.length-1).replace(/\\"/g,'"');c.toString=function(){return'"'+this.value+'"'}}else{c.type="id";c.lineNo=b;c.value=
a;c.toString=function(){return"'"+this.value}}return c};wisp.parseIsNumber=function(a){return!isNaN(parseFloat(a))};wisp.parseIsBoolean=function(a){return a==="true"||a==="false"};wisp.parseIsString=function(a){return typeof a==="string"&&a[0]==='"'&&a[a.length-1]==='"'};wisp.interpArgs=function(a,b){if(wisp.isEmpty(a))return a;return wisp.cons(wisp.interp(wisp.first(a),b),wisp.interpArgs(wisp.rest(a),b))};
wisp.interpCond=function(a,b){if(wisp.isEmpty(a))return a;var c=wisp.interp(wisp.first(wisp.first(a)),b);wisp.verifyBoolean(c);return c.value?wisp.interp(wisp.second(wisp.first(a)),b):wisp.interpCond(wisp.rest(a),b)};wisp.interpSeq=function(a,b){if(wisp.isEmpty(wisp.rest(a)))return wisp.interp(wisp.first(a),b);else{wisp.interp(wisp.first(a),b);return wisp.interpSeq(wisp.rest(a),b)}};
wisp.interpWhile=function(a,b,c){var d,e=wisp.verifyBoolean(wisp.interp(a,c));for(d=e;e.value===true;){d=wisp.interp(b,c);e=wisp.interp(a,c)}return d};
wisp.interpQuote=function(a,b,c){if(!wisp.isCons(a)||wisp.isEmpty(a))return a;if(c){var d=wisp.first(a);if(wisp.isAbstractIdentifier(d)&&d.value==="unquote")return wisp.interp(wisp.second(a),b);if(wisp.isCons(d)&&wisp.isAbstractIdentifier(wisp.first(d))&&wisp.first(d).value==="unquote-splice"){a=wisp.interpQuote(wisp.rest(a),b,c);b=wisp.interp(wisp.second(d),b);return wisp.append(b,a)}}return wisp.cons(wisp.interpQuote(wisp.first(a),b,c),wisp.interpQuote(wisp.rest(a),b,c))};
wisp.envSet=function(a,b,c){var d=c[c.__currentNamespace];a=wisp.verifyIdentifier(a).value;d[a]=b;return c};wisp.envLookup=function(a,b){var c,d=wisp.verifyIdentifier(a).value,e,f=b.__currentNamespace;for(e=0;e<(f.length&&c===undefined);e++)c=b[f][d];if(c===undefined)c=b[d];if(c===undefined)wisp.exceptionHelper("Unbound identifier: "+d+" isn't defined in the current scope.",[a]);else return c};
wisp.copyEnv=function(a){var b,c,d=a.__allNamespaces;b=$.extend({},a);for(c=0;c<d.length;c++)b[d[c]]=$.extend({},a[d[c]]);return b};
wisp.addArgsToEnv=function(a,b,c){if(wisp.isEmpty(a))return c;var d=wisp.verifyIdentifier(wisp.first(a));if(d.value[0]==="&"){var e={};e.type="id";e.value=d.value.substring(1);e.toString=function(){return"'"+this.value};wisp.envSet(e,b,c);return c}else if(wisp.isEmpty(b))throw"Wisp error: insufficient number of arguments given";else{e=wisp.first(b);b=wisp.addArgsToEnv(wisp.rest(a),wisp.rest(b),c);wisp.envSet(d,e,b);return b}};
wisp.macroExpand=function(a,b,c){a=wisp.verifyMacroClosure(wisp.interp(a,c));return wisp.interp(a.body,wisp.addArgsToEnv(a.params,b,a.savedEnv))};
wisp.unboxAbstractSyntax=function(a){if(wisp.isEmpty(a))return a;var b=wisp.first(a);if(wisp.isAbstractNumber(b)||wisp.isAbstractString(b)||wisp.isAbstractBoolean(b))return wisp.cons(b.value,wisp.unboxAbstractSyntax(wisp.rest(a)));else if(wisp.isAbstractIdentifier(b))return wisp.cons(b,wisp.unboxAbstractSyntax(wisp.rest(a)));else if(wisp.isCons(b))return wisp.cons(wisp.unboxAbstractSyntax(b),wisp.unboxAbstractSyntax(wisp.rest(a)));else throw"Unrecognized value "+b+" tried to be passed to native javascript function";
};
wisp.boxJavascriptValue=function(a){var b={};if(wisp.isBoolean(a)){b.type="bool";b.value=a===true;b.toString=function(){return this.value+""}}else if(wisp.isNumber(a)){b.type="number";b.value=a;b.toString=function(){return this.value+""}}else if(wisp.isString(a)){b.type="string";b.value=a;b.toString=function(){return'"'+this.value+'"'}}else if(wisp.isAbstractIdentifier(a))return a;else if(wisp.isCons(a))return wisp.isEmpty(a)?a:wisp.cons(wisp.boxJavascriptValue(wisp.first(a)),wisp.boxJavascriptValue(wisp.rest(a)));else{b.type=
"string";b.value=a+"";b.toString=function(){return'"'+this.value+'"'}}return b};
wisp.interp=function(a,b){var c,d;if(wisp.isAbstractNumber(a)||wisp.isAbstractString(a)||wisp.isAbstractBoolean(a))return a;else if(wisp.isAbstractIdentifier(a))return wisp.envLookup(a,b);else if(wisp.isCons(a)){c=wisp.first(a);if(wisp.isAbstractIdentifier(c))switch(c.value){case "quote":return wisp.interpQuote(wisp.second(a),b,false);case "backquote":return wisp.interpQuote(wisp.second(a),b,true);case "unquote":throw"Wisp Error: Unquote must occur within a backquote";case "lambda":c=wisp.copyEnv(b);
return{type:"lambdaClosure",body:wisp.third(a),params:wisp.second(a),savedEnv:c,toString:function(){return"(list 'lambda "+this.params.toString()+" "+this.body.toString()+")"}};case "macro":c=wisp.copyEnv(b);return{type:"macroClosure",body:wisp.third(a),params:wisp.second(a),savedEnv:c,toString:function(){return"(list 'macro "+this.params.toString()+" "+this.body.toString()+")"}};case "macroexpand":return wisp.macroExpand(wisp.first(wisp.first(wisp.rest(a))),wisp.rest(wisp.first(wisp.rest(a))),b);
case "cond":return wisp.interpCond(wisp.rest(a),b);case "eval":return wisp.interp(wisp.interp(wisp.first(wisp.rest(a)),b),b);case "def":c=wisp.interp(wisp.third(a),b);wisp.envSet(wisp.second(a),c,b);if(wisp.isAbstractLambdaClosure(c)||wisp.isAbstractMacroClosure(c))wisp.envSet(wisp.second(a),c,c.savedEnv);return c;case "seq":return wisp.interpSeq(wisp.rest(a),b);case "while":return wisp.interpWhile(wisp.second(a),wisp.third(a),b)}c=wisp.interp(wisp.first(a),b);if(wisp.isAbstractLambdaClosure(c)){d=
wisp.interpArgs(wisp.rest(a),b);return wisp.interp(c.body,wisp.addArgsToEnv(c.params,d,c.savedEnv))}else if(wisp.isAbstractMacroClosure(c))return wisp.interp(wisp.macroExpand(wisp.first(a),wisp.rest(a),b),b);else if(typeof c==="function"){d=wisp.interpArgs(wisp.rest(a),b);c=c(wisp.unboxAbstractSyntax(d),b);return wisp.boxJavascriptValue(c)}throw"Application expression is invalid (neither a function nor macro): "+c;}else throw"Wisp Error: Given s-expression "+a+" of unknown type";};
wisp.basicEnv={__currentNamespace:"default",__allNamespaces:["default"],"+":function(a){return wisp.isEmpty(wisp.rest(a))?wisp.first(a):wisp.first(a)+arguments.callee(wisp.rest(a))},"-":function(a){if(wisp.isEmpty(a))return 0;return wisp.first(a)-arguments.callee(wisp.rest(a))},"*":function(a){if(wisp.isEmpty(a))return 1;return wisp.first(a)*arguments.callee(wisp.rest(a))},"/":function(a){if(wisp.isEmpty(a))return 1;return wisp.first(a)/arguments.callee(wisp.rest(a))},"%":function(a){return wisp.first(a)%
wisp.second(a)},">":function(a){return wisp.first(a)>wisp.second(a)},">=":function(a){return wisp.first(a)>=wisp.second(a)},"<":function(a){return wisp.first(a)<wisp.second(a)},"<=":function(a){return wisp.first(a)<=wisp.second(a)},not:function(a){return!wisp.first(a)},and:function(a){return wisp.isEmpty(wisp.rest(a))?wisp.first(a):wisp.first(a)&&arguments.callee(wisp.rest(a))},or:function(a){return wisp.isEmpty(wisp.rest(a))?wisp.first(a):wisp.first(a)||arguments.callee(wisp.rest(a))},list:function(a){return a},
first:function(a){return wisp.first(wisp.first(a))},rest:function(a){return wisp.rest(wisp.first(a))},cons:function(a){return wisp.cons(wisp.first(a),wisp.second(a))},"list?":function(a){return wisp.isCons(wisp.first(a))},"atom?":function(a){return wisp.isAtom(wisp.first(a))},"empty?":function(a){return wisp.isEmpty(wisp.first(a))},"eq?":function(a){var b=wisp.first(a),c=wisp.second(a);if(wisp.isAtom(b)&&wisp.isAtom(c))return b===c;else if(wisp.isAbstractIdentifier(b)&&wisp.isAbstractIdentifier(c))return b.value===
c.value;else if(wisp.isEmpty(b)&&wisp.isEmpty(c))return true;else if(wisp.isNonEmptyCons(b)&&wisp.isNonEmptyCons(c)){var d=wisp.cons(wisp.first(b),wisp.cons(wisp.first(c),wisp.empty));if(wisp.isEmpty(wisp.rest(b))&&wisp.isEmpty(wisp.rest(c)))return arguments.callee(d);b=wisp.cons(wisp.rest(b),wisp.cons(wisp.rest(c),wisp.empty));return arguments.callee(d)&&arguments.callee(b)}else return false},append:function(a){if(wisp.isEmpty(wisp.rest(a)))return wisp.first(a);return wisp.append(wisp.first(a),arguments.callee(wisp.rest(a)))},
read:function(a){return wisp.read(wisp.first(a))},"number?":function(a){return wisp.isNumber(wisp.first(a))},"boolean?":function(a){return wisp.isBoolean(wisp.first(a))},"string?":function(a){return wisp.isString(wisp.first(a))},log:function(a){if(wisp.isEmpty(a))return wisp.empty;else{console.log(wisp.first(a));return wisp.cons(wisp.first(a),arguments.callee(wisp.rest(a)))}},split:function(a){return wisp.second(a).split(wisp.first(a)).toWispSexp()},write:function(a){document.write(wisp.first(a));
return wisp.isEmpty(wisp.rest(a))?wisp.first(a):arguments.callee(wisp.rest(a))},"append-body":function(a){$("body").append(wisp.first(a));return wisp.isEmpty(wisp.rest(a))?wisp.first(a):arguments.callee(wisp.rest(a))},writeln:function(a){document.writeln(wisp.first(a));return wisp.isEmpty(wisp.rest(a))?wisp.first(a):arguments.callee(wisp.rest(a))},random:function(a){return wisp.isEmpty(a)?Math.random():Math.floor(Math.random()*wisp.first(a))},"default":{},"set-ns":function(a,b){var c,d=wisp.first(a),
e=false,f=b.__allNamespaces;for(c=0;c<f.length;c++)if(f[c]===d){e=true;break}if(!e){if(!wisp.isString(d))throw"namespace must be a string";b[d]={};f.push(d)}return b.__currentNamespace=d},"get-ns":function(a,b){return b.__currentNamespace}};wisp.scripts=[];var i,links=document.getElementsByTagName("link"),typePattern=/^text\/(x-)?wisp$/;for(i=0;i<links.length;i++)if(links[i].rel==="script/wisp"||links[i].rel.match(/script/)&&links[i].type.match(typePattern))wisp.scripts.push(links[i]);
var val,advance,read,sexps,env=wisp.basicEnv,scriptIndex=0;
wisp.readNextScript=function(){$.get(wisp.scripts[scriptIndex].href,function(a){a=a.trim();advance={index:0,lineNumber:1};for(sexps=[];advance.index<a.length;){read=wisp.read(a,advance);read!==wisp.COMMENT&&read!==wisp.EOF&&sexps.push(read)}for(i=0;i<sexps.length;i++)val=wisp.interp(sexps[i],env);a=wisp.isCons(val)?val.toWispString():val;console.log(wisp.scripts[scriptIndex].href+" returned: \n"+a);scriptIndex++;scriptIndex<wisp.scripts.length&&wisp.readNextScript()})};wisp.scripts.length>0&&wisp.readNextScript();