Plugin Directory

Changeset 2208785


Ignore:
Timestamp:
12/09/2019 06:55:03 PM (6 years ago)
Author:
gtanyware
Message:

Version 2.5.3 Revised run/import handling

Location:
easycoder/trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • easycoder/trunk/easycoder-min.js

    r2168730 r2208785  
    1 var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(d,k,h){d!=Array.prototype&&d!=Object.prototype&&(d[k]=h.value)};$jscomp.getGlobal=function(d){return"undefined"!=typeof window&&window===d?d:"undefined"!=typeof global&&null!=global?global:d};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
    2 $jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.Symbol=function(){var d=0;return function(k){return $jscomp.SYMBOL_PREFIX+(k||"")+d++}}();
    3 $jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var d=$jscomp.global.Symbol.iterator;d||(d=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[d]&&$jscomp.defineProperty(Array.prototype,d,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(d){var k=0;return $jscomp.iteratorPrototype(function(){return k<d.length?{done:!1,value:d[k++]}:{done:!0}})};
    4 $jscomp.iteratorPrototype=function(d){$jscomp.initSymbolIterator();d={next:d};d[$jscomp.global.Symbol.iterator]=function(){return this};return d};$jscomp.makeIterator=function(d){$jscomp.initSymbolIterator();var k=d[Symbol.iterator];return k?k.call(d):$jscomp.arrayIterator(d)};$jscomp.owns=function(d,k){return Object.prototype.hasOwnProperty.call(d,k)};
    5 $jscomp.assign="function"==typeof Object.assign?Object.assign:function(d,k){for(var h=1;h<arguments.length;h++){var g=arguments[h];if(g)for(var c in g)$jscomp.owns(g,c)&&(d[c]=g[c])}return d};$jscomp.polyfill=function(d,k,h,g){if(k){h=$jscomp.global;d=d.split(".");for(g=0;g<d.length-1;g++){var c=d[g];c in h||(h[c]={});h=h[c]}d=d[d.length-1];g=h[d];k=k(g);k!=g&&null!=k&&$jscomp.defineProperty(h,d,{configurable:!0,writable:!0,value:k})}};
    6 $jscomp.polyfill("Object.assign",function(d){return d||$jscomp.assign},"es6","es3");$jscomp.iteratorFromArray=function(d,k){$jscomp.initSymbolIterator();d instanceof String&&(d+="");var h=0,g={next:function(){if(h<d.length){var c=h++;return{value:k(c,d[c]),done:!1}}g.next=function(){return{done:!0,value:void 0}};return g.next()}};g[Symbol.iterator]=function(){return g};return g};
    7 $jscomp.polyfill("Array.prototype.keys",function(d){return d?d:function(){return $jscomp.iteratorFromArray(this,function(d){return d})}},"es6","es3");$jscomp.checkStringArgs=function(d,k,h){if(null==d)throw new TypeError("The 'this' value for String.prototype."+h+" must not be null or undefined");if(k instanceof RegExp)throw new TypeError("First argument to String.prototype."+h+" must not be a regular expression");return d+""};
    8 $jscomp.polyfill("String.prototype.endsWith",function(d){return d?d:function(d,h){var g=$jscomp.checkStringArgs(this,d,"endsWith");d+="";void 0===h&&(h=g.length);h=Math.max(0,Math.min(h|0,g.length));for(var c=d.length;0<c&&0<h;)if(g[--h]!=d[--c])return!1;return 0>=c}},"es6","es3");$jscomp.polyfill("Object.is",function(d){return d?d:function(d,h){return d===h?0!==d||1/d===1/h:d!==d&&h!==h}},"es6","es3");
    9 $jscomp.polyfill("Array.prototype.includes",function(d){return d?d:function(d,h){var g=this;g instanceof String&&(g=String(g));var c=g.length;h=h||0;for(0>h&&(h=Math.max(h+c,0));h<c;h++){var a=g[h];if(a===d||Object.is(a,d))return!0}return!1}},"es7","es3");$jscomp.polyfill("String.prototype.includes",function(d){return d?d:function(d,h){return-1!==$jscomp.checkStringArgs(this,d,"includes").indexOf(d,h||0)}},"es6","es3");
    10 $jscomp.polyfill("Math.trunc",function(d){return d?d:function(d){d=Number(d);if(isNaN(d)||Infinity===d||-Infinity===d||0===d)return d;var k=Math.floor(Math.abs(d));return 0>d?-k:k}},"es6","es3");$jscomp.polyfill("String.prototype.repeat",function(d){return d?d:function(d){var k=$jscomp.checkStringArgs(this,null,"repeat");if(0>d||1342177279<d)throw new RangeError("Invalid count value");d|=0;for(var g="";d;)if(d&1&&(g+=k),d>>>=1)k+=k;return g}},"es6","es3");
    11 $jscomp.stringPadding=function(d,k){d=void 0!==d?String(d):" ";return 0<k&&d?d.repeat(Math.ceil(k/d.length)).substring(0,k):""};$jscomp.polyfill("String.prototype.padStart",function(d){return d?d:function(d,h){var g=$jscomp.checkStringArgs(this,null,"padStart");return $jscomp.stringPadding(h,d-g.length)+g}},"es8","es3");$jscomp.polyfill("Number.isFinite",function(d){return d?d:function(d){return"number"!==typeof d?!1:!isNaN(d)&&Infinity!==d&&-Infinity!==d}},"es6","es3");
    12 $jscomp.polyfill("Number.isInteger",function(d){return d?d:function(d){return Number.isFinite(d)?d===Math.floor(d):!1}},"es6","es3");
    13 (function(){function d(k,h,g){function c(b,q){if(!h[b]){if(!k[b]){var e="function"==typeof require&&require;if(!q&&e)return e(b,!0);if(a)return a(b,!0);q=Error("Cannot find module '"+b+"'");throw q.code="MODULE_NOT_FOUND",q;}q=h[b]={exports:{}};k[b][0].call(q.exports,function(a){return c(k[b][1][a]||a)},q,q.exports,d,k,h,g)}return h[b].exports}for(var a="function"==typeof require&&require,b=0;b<g.length;b++)c(g[b]);return c}return d})()({1:[function(d,k,h){var g=d("./easycoder/Main");g.version="2.5.2";
    14 g.timestamp=Date.now();console.log("EasyCoder loaded; waiting for page");window.onload=function(){console.log(Date.now()-g.timestamp+" ms: Page loaded; reset timer & start EasyCoder");g.timestamp=Date.now();g.scripts={};window.EasyCoder=g;var c=document.getElementById("easycoder-script");if(c){c.style.display="none";try{g.start(c.innerText)}catch(a){g.reportError(a)}}}},{"./easycoder/Main":6}],2:[function(d,k,h){k.exports=function(d,c,a){c=d.value.evaluate(d,c);d=d.value.evaluate(d,a);a=c.content;
    15 var b=d.content;a&&c.numeric?d.numeric||(b="undefined"===typeof b?0:parseInt(b)):(b&&d.numeric&&(b=b.toString()),"undefined"===typeof a&&(a=""),"undefined"===typeof b&&(b=""));return a>b?1:a<b?-1:0}},{}],3:[function(d,k,h){var g=Object.assign||function(a){for(var b=1;b<arguments.length;b++){var c=arguments[b],f;for(f in c)Object.prototype.hasOwnProperty.call(c,f)&&(a[f]=c[f])}return a},c=this,a={getTokens:function(){return c.tokens},addWarning:function(a){c.warnings.push(a)},warning:function(b){a.addWarning(b)},
    16 unrecognisedSymbol:function(b){a.addWarning("Unrecognised symbol '"+b+"'")},getWarnings:function(){return c.warnings},getIndex:function(){return c.index},next:function(a){c.index+=void 0===a?1:a},peek:function(){return c.tokens[c.index+1].token},more:function(){return c.index<c.tokens.length},getToken:function(){return c.index>=c.tokens.length?null:c.tokens[c.index]?c.tokens[c.index].token:null},nextToken:function(){a.next();return a.getToken()},tokenIs:function(a){return c.index>=c.tokens.length?
    17 !1:a===c.tokens[c.index].token},nextTokenIs:function(b){a.next();return a.tokenIs(b)},skip:function(b){if(c.index>=c.tokens.length)return null;a.next();a.tokenIs(b)&&a.next()},prev:function(){c.index--},getLino:function(){return c.index>=c.tokens.length?0:c.tokens[c.index].lino},getTarget:function(a){a=void 0===a?c.index:a;return c.tokens[a].token},getTargetPc:function(b){b=void 0===b?c.index:b;return c.symbols[a.getTarget(b)].pc},getCommandAt:function(a){return c.program[a]},isSymbol:function(b){b=
    18 void 0===b?!1:b;if(a.getTarget()in c.symbols)return!0;if(b)throw Error("Unknown symbol: '"+a.getTarget()+"'");return!1},nextIsSymbol:function(b){b=void 0===b?!1:b;a.next();return a.isSymbol(b)},getSymbol:function(){return c.symbols[a.getToken()]},getSymbolPc:function(){return a.getSymbol().pc},getSymbolRecord:function(){var b=c.program[a.getSymbolPc()];b.used=!0;return b},getSymbols:function(){return c.symbols},getProgram:function(){return c.program},getPc:function(){return c.program.length},getValue:function(){return a.value.compile(a)},
    19 getNextValue:function(){a.next();return a.getValue()},getCondition:function(){return a.condition.compile(a)},constant:function(b,e){return a.value.constant(b,void 0===e?!1:e)},addCommand:function(a){c.program.push(g({pc:c.program.length},a))},addSymbol:function(a,e){c.symbols[a]={pc:e}},mark:function(){c.savedMark=c.index},rewind:function(){c.index=c.savedMark},rewindTo:function(a){c.index=a},completeHandler:function(){var b=a.getLino(),e=a.getPc();a.addCommand({domain:"core",keyword:"goto",lino:b,
    20 goto:0});a.compileOne();a.addCommand({domain:"core",keyword:"stop",lino:b,next:0});a.getCommandAt(e).goto=a.getPc();return!0},compileVariable:function(b,e,q,f){q=void 0===q?!1:q;f=void 0===f?null:f;a.next();var l=a.getLino(),d=a.getTokens()[a.getIndex()];if(c.symbols[d.token])throw Error("Duplicate variable name '"+d.token+"'");var g=a.getPc();a.next();a.addSymbol(d.token,g);b={domain:b,keyword:e,lino:l,isSymbol:!0,used:!1,isValueHolder:q,name:d.token,elements:1,index:0,value:[{}],element:[],extra:f};
    21 "dom"===f&&(b.element=[]);a.addCommand(b);return b},compileToken:function(){var b=a.getToken();if(b){a.mark();for(var e=$jscomp.makeIterator(Object.keys(a.domain)),c=e.next();!c.done;c=e.next()){if((c=a.domain[c.value])&&(c=c.getHandler(b))&&c.compile(a))return;a.rewind()}console.log("No handler found");throw Error("I don't understand '"+b+"...'");}},compileOne:function(){var b=a.getToken();if(b){c.warnings=[];var e=c.program.length;if(b.endsWith(":")){b=b.substring(0,b.length-1);if(c.symbols[b])throw Error("Duplicate symbol: '"+
    22 b+"'");c.symbols[b]={pc:e};c.index++}else a.compileToken()}},compileFromHere:function(b){for(;c.index<c.tokens.length;){var e=c.tokens[c.index].token;if("else"===e)return c.program;a.compileOne();if(-1<b.indexOf(e))break}},compile:function(b){c.tokens=b;c.index=0;c.program=[];c.symbols={};c.warnings=[];a.compileFromHere([]);a.addCommand({domain:"core",keyword:"exit",lino:a.getLino(),next:0});for(var e in c.symbols)b=c.program[c.symbols[e].pc],b.isSymbol&&!b.used&&console.log("Symbol '"+b.name+"' has not been used.");
    23 return c.program}};k.exports=a},{}],4:[function(d,k,h){var g=Object.assign||function(c){for(var a=1;a<arguments.length;a++){var b=arguments[a],e;for(e in b)Object.prototype.hasOwnProperty.call(b,e)&&(c[e]=b[e])}return c};k.exports={compile:function(c){c.mark();for(var a=$jscomp.makeIterator(Object.keys(c.domain)),b=a.next();!b.done;b=a.next()){if(b=c.domain[b.value].condition.compile(c))return g({domain:name},b);c.rewind()}},test:function(c,a){return c.domain[a.domain].condition.test(c,a)}}},{}],
    24 5:[function(d,k,h){var g=this,c={Add:{compile:function(a){var b=a.getLino();a.next();var e=a.getValue();if(a.tokenIs("to"))if(a.next(),a.isSymbol()){var c=a.getSymbol();if(a.getCommandAt(c.pc).isValueHolder){if("giving"===a.peek()){c=a.getValue();a.next();var d=a.getToken();a.next();a.addCommand({domain:"core",keyword:"add",lino:b,value1:e,value2:c,target:d})}else c=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"add",lino:b,value1:e,target:c});return!0}a.warning("core "+g.name+": Expected value holder")}else{c=
    25 a.getValue();if(a.tokenIs("giving"))return a.next(),d=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"add",lino:b,value1:e,value2:c,target:d}),!0;a.warning("core "+g.name+': Expected "giving"')}return!1},run:function(a){var b=a[a.pc],e=b.value1,c=b.value2,d=a.getSymbolRecord(b.target);if(d.isValueHolder){var l=d.value[d.index];c?(a=a.getValue(c)+a.getValue(e),d.value[d.index]={type:"constant",numeric:!0,content:a}):(!l.numeric&&isNaN(l.content)&&a.nonNumericValueError(b.lino),a=parseInt(l.content)+
    26 parseInt(a.getValue(e)),d.value[d.index]={type:"constant",numeric:!0,content:a})}else a.variableDoesNotHoldAValueError(b.lino,d.name);return b.pc+1}},Alias:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var e=a.getToken();a.next();if(a.tokenIs("to")&&(a.next(),a.isSymbol())){var c=a.getSymbolRecord();c.used=!0;a.next();a.addCommand({domain:"core",keyword:"alias",lino:b,alias:e,symbol:c.name});return!0}}return!1},run:function(a){var b=a[a.pc],e=a.symbols[b.alias].pc,c=a[e],d=a.getSymbolRecord(b.symbol);
    27 a[e]={pc:c.pc,domain:d.domain,keyword:d.keyword,lino:c.lino,name:c.name,alias:b.symbol};return b.pc+1}},Append:{compile:function(a){var b=a.getLino(),e=a.getNextValue();if(a.tokenIs("to")&&a.nextIsSymbol()){var c=a.getSymbolRecord();if(c.isValueHolder)return a.next(),a.addCommand({domain:"core",keyword:"append",lino:b,value:e,select:c.name}),!0}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.select);try{var c=a.getValue(b.value),d=["{","["].includes(c[0])?JSON.parse(c):c,l=e.value[e.index],
    28 n=l.content;n=n?JSON.parse(n):[];n.push(d);l.content=JSON.stringify(n);return b.pc+1}catch(p){return a.runtimeError(b.lino,"JSON: Unable to parse value"),!1}}},Begin:{compile:function(a){a.next();a.compileFromHere(["end"]);return!0},run:function(a){return a[a.pc].pc+1}},Callback:{compile:function(a){a.compileVariable("core","callback");return!0},run:function(a){return a[a.pc].pc+1}},Clear:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var e=a.getSymbolRecord();if(e.isValueHolder)return e=
    29 a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"clear",lino:b,symbol:e}),!0;a.warning("'Variable '"+e.name+"' does not hold a value")}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.symbol);e.isValueHolder?(a.domain[e.domain].value.put(e,{type:"boolean",content:!1}),b.numeric=!1):a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},Close:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var e=a.getSymbolRecord();if("module"===e.keyword)return a.next(),
    30 a.addCommand({domain:"core",keyword:"close",lino:b,module:e.name}),!0}return!1},run:function(a){var b=a[a.pc];a=a.getSymbolRecord(b.module).program;a.run(a.onClose);return b.pc+1}},Debug:{compile:function(a){var b=a.getLino();if(a.nextTokenIs("program")){a.next();if(["item","pc"].includes(a.getToken())){var e=a.getNextValue();a.addCommand({domain:"core",keyword:"debug",lino:b,item:e});return!0}a.addCommand({domain:"core",keyword:"debug",lino:b,item:"program"});return!0}return a.tokenIs("symbols")?
    31 (a.next(),a.addCommand({domain:"core",keyword:"debug",lino:b,item:"symbols"}),!0):a.tokenIs("symbol")?(e=a.nextToken(),a.next(),a.addCommand({domain:"core",keyword:"debug",lino:b,item:"symbol",name:e}),!0):a.tokenIs("step")?(a.next(),a.addCommand({domain:"core",keyword:"debug",lino:b,item:"step"}),!0):!1},run:function(a){var b=a[a.pc],e=b.item;switch(e){case "symbols":console.log("Symbols: "+JSON.stringify(a.symbols,null,2));break;case "symbol":a=a.getSymbolRecord(b.name);e=a.exporter;delete a.exporter;
    32 console.log("Symbol: "+JSON.stringify(a,null,2));a.exporter=e;break;case "step":a.debugStep=!0;break;case "program":console.log("Debug program: "+JSON.stringify(a,null,2));break;default:0<=e.content&&console.log("Debug item "+e.content+": "+JSON.stringify(a[e.content],null,2))}return b.pc+1}},Decode:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var e=a.getToken();a.next();a.addCommand({domain:"core",keyword:"decode",lino:b,symbol:e});return!0}return!1},run:function(a){var b=a[a.pc],
    33 e=a.getSymbolRecord(b.symbol);if(e.isValueHolder){var c=a.getValue(e.value[e.index]);e.value[e.index]={type:"constant",numeric:!1,content:a.decode(c)};b.numeric=!1}else a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},Divide:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var e=a.getSymbol();var c=a.getCommandAt(e.pc).name}e=a.getValue();a.tokenIs("by")&&a.next();var d=a.getValue();if(a.tokenIs("giving")){a.next();if(a.isSymbol())return c=a.getSymbol(),c=a.getCommandAt(c.pc).name,
    34 a.next(),a.addCommand({domain:"core",keyword:"divide",lino:b,value1:e,value2:d,target:c}),!0;a.warning("core "+g.name+": Expected value holder")}else return"undefined"===typeof c&&a.warning("core "+g.name+": No target variable given"),a.addCommand({domain:"core",keyword:"divide",lino:b,value2:d,target:c}),!0;return!1},run:function(a){var b=a[a.pc],e=b.value1,c=b.value2,d=a.getSymbolRecord(b.target);if(d.isValueHolder){var l=d.value[d.index];e?(a=a.getValue(e)/a.getValue(c),d.value[d.index]={type:"constant",
    35 numeric:!0,content:Math.trunc(a)}):(!l.numeric&&isNaN(l.content)&&a.nonNumericValueError(b,lino),a=parseInt(l.content)/parseInt(a.getValue(c)),d.value[d.index]={type:"constant",numeric:!0,content:Math.trunc(a)})}else a.variableDoesNotHoldAValueError(b.lino,d.name);return b.pc+1}},Dummy:{compile:function(a){var b=a.getLino();a.next();a.addCommand({domain:"core",keyword:"dummy",lino:b});return!0},run:function(a){return a[a.pc].pc+1}},Encode:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var e=
    36 a.getToken();a.next();a.addCommand({domain:"core",keyword:"encode",lino:b,symbol:e});return!0}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.symbol);if(e.isValueHolder){var c=a.getValue(e.value[e.index]);e.value[e.index]={type:"constant",numeric:!1,content:a.encode(c)};b.numeric=!1}else a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},End:{compile:function(a){a.next();return!0},run:function(){return 0}},Exit:{compile:function(a){a.next();a.addCommand({domain:"core",keyword:"exit"});
    37 return!0},run:function(a){a.exit();return 0}},Filter:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var e=a.getSymbolRecord();if(a.nextTokenIs("with")){var c=a.nextToken();a.next();a.addCommand({domain:"core",keyword:"filter",lino:b,array:e.name,func:c});return!0}}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.array),c=e.value[e.index].content,d=a.getSymbolRecord(b.func).pc;try{var l=JSON.parse(c).filter(function(b){e.a=b;a.run(d);return e.v});e.value[e.index].content=
    38 JSON.stringify(l)}catch(n){a.runtimeError(b.lino,"Can't parse this array")}return b.pc+1}},Fork:{compile:function(a){var b=a.getLino();a.next();a.nextTokenIs("to")&&a.next();var e=a.getToken();a.next();a.addCommand({domain:"core",keyword:"fork",lino:b,label:e});return!0},run:function(a){var b=a[a.pc];try{a.run(a.symbols[b.label].pc)}catch(e){console.log(e.message),alert(e.message)}return b.pc+1}},Go:{compile:function(a){var b=a.getLino();a.nextTokenIs("to")&&a.next();var e=a.getToken();a.next();a.addCommand({domain:"core",
    39 keyword:"go",lino:b,label:e});return!0},run:function(a){var b=a[a.pc];if(b.label){if(a.verifySymbol(b.label)){var e=a.symbols[b.label];if(e)return e.pc}a.runtimeError(b.lino,"Unknown symbol '"+b.label+"'");return 0}return b.goto}},Gosub:{compile:function(a){var b=a.getLino();a.nextTokenIs("to")&&a.next();var e=a.getToken();a.next();a.addCommand({domain:"core",keyword:"gosub",lino:b,label:e});return!0},run:function(a){var b=a[a.pc];if(a.verifySymbol(b.label))return a.stack.push(a.pc+1),a.symbols[b.label].pc;
    40 a.runtimeError(b.lino,"Unknown symbol '"+b.label+"'");return 0}},If:{compile:function(a){var b=a.getLino();a.next();var e=a.condition.compile(a),c=a.getPc();a.addCommand({domain:"core",keyword:"if",lino:b,condition:e});a.compileOne();if(!a.getToken())return a.getCommandAt(c).else=a.getPc(),!0;a.tokenIs("else")?(b=a.getPc(),a.addCommand({domain:"core",keyword:"goto",goto:0}),a.getCommandAt(c).else=a.getPc(),a.next(),a.compileOne(!0),a.getCommandAt(b).goto=a.getPc()):a.getCommandAt(c).else=a.getPc();
    41 return!0},run:function(a){var b=a[a.pc];return a.condition.test(a,b.condition)?b.pc+1:b.else}},Import:{compile:function(a){var b=a.imports,e=a.getProgram();if(b.length){b=$jscomp.makeIterator(b);for(var c=b.next();!c.done;c=b.next()){c=c.value;var d=a.nextToken(),l=c.keyword;if(d===l){if(d=a.compileVariable(c.domain,l,!0),d=e[a.getSymbols()[d.name].pc],d.element=c.element,d.exporter=c.exporter,d.exportedName=c.name,d.extra=c.extra,d.isValueHolder=c.isValueHolder,d.imported=!0,!a.tokenIs("and"))break}else throw Error("Mismatched import variable type for '"+
    42 c.name+"'");}if(a.tokenIs("and"))throw Error("Imports do not match exports");}else a.next();return!0},run:function(a){return a[a.pc].pc+1}},Index:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol(!0)){var e=a.getToken();if(a.nextTokenIs("to")){var c=a.getNextValue();a.addCommand({domain:"core",keyword:"index",lino:b,symbol:e,value:c});return!0}}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.symbol),c=a.getValue(b.value);c>=e.elements&&a.runtimeError(b.lino,"Array index "+c+" is out of range for '"+
    43 e.name+"'");e.index=c;e.imported&&(e.exporter.getSymbolRecord(e.exportedName).index=c);return b.pc+1}},Load:{compile:function(a){var b=a.getLino();switch(a.nextToken()){case "plugin":var e=a.getNextValue();a.addCommand({domain:"core",keyword:"load",lino:b,name:e});return!0}return!1},run:function(a){var b=a[a.pc],e=a.getValue(b.name);switch(b.keyword){case "load":if(a.checkPlugin(e))return b.pc+1;EasyCoder_Plugins.getLocalPlugin(a.getPluginsPath,e,a.getPlugin,a.addLocalPlugin,function(){a.run(b.pc+
    44 1)});return 0}}},Module:{compile:function(a){a.compileVariable("core","module");return!0},run:function(a){a=a[a.pc];a.program=null;return a.pc+1}},Multiply:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var e=a.getSymbol();var c=a.getCommandAt(e.pc).name}e=a.getValue();a.tokenIs("by")&&a.next();var d=a.getValue();if(a.tokenIs("giving")){a.next();if(a.isSymbol())return c=a.getSymbol(),c=a.getCommandAt(c.pc).name,a.next(),a.addCommand({domain:"core",keyword:"multiply",lino:b,value1:e,
    45 value2:d,target:c}),!0;a.warning("core multiply: Expected value holder")}else return"undefined"===typeof c&&a.warning("core multiply: No target variable given"),a.addCommand({domain:"core",keyword:"multiply",lino:b,value2:d,target:c}),!0;return!1},run:function(a){var b=a[a.pc],e=b.value1,c=b.value2,d=a.getSymbolRecord(b.target);if(d.isValueHolder){var l=d.value[d.index];e?(a=a.getValue(e)*a.getValue(c),d.value[d.index]={type:"constant",numeric:!0,content:a}):(!l.numeric&&isNaN(l.content)&&a.nonNumericValueError(b,
    46 lino),a=parseInt(l.content)*parseInt(a.getValue(c)),d.value[d.index]={type:"constant",numeric:!0,content:a})}else a.variableDoesNotHoldAValueError(b.lino,d.name);return b.pc+1}},Negate:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var e=a.getToken();a.next();a.addCommand({domain:"core",keyword:"negate",lino:b,symbol:e});return!0}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.symbol);e.isValueHolder?e.value[e.index]={type:"constant",numeric:!0,content:-e.value[e.index].content}:
    47 a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},On:{compile:function(a){var b=a.getLino(),e=a.nextToken();switch(e){case "close":case "message":case "error":return a.next(),a.addCommand({domain:"core",keyword:"on",lino:b,action:e}),a.completeHandler()}return a.isSymbol()&&(e=a.getSymbolRecord(),"callback"===e.keyword)?(a.next(),a.addCommand({domain:"core",keyword:"on",lino:b,action:e.name}),a.completeHandler()):!1},run:function(a){var b=a[a.pc],e=b.pc+2;switch(b.action){case "close":a.onClose=
    48 e;break;case "message":a.onMessage=e;break;case "error":a.onError=e;break;default:var c=a.getSymbolRecord(b.action);if(c)c.cb=e;else return a.runtimeError(b.lino,"Unknown action '"+b.action+"'"),0}return b.pc+1}},Print:{compile:function(a){var b=a.getLino();a.next();var e=a.getValue();a.addCommand({domain:"core",keyword:"print",lino:b,value:e});return!0},run:function(a){var b=a[a.pc];a=a.getFormattedValue(b.value);console.log("-> "+a);return b.pc+1}},Put:{compile:function(a){var b=a.getLino(),e=a.getNextValue();
    49 if(a.tokenIs("into")){if(a.nextIsSymbol()){var c=a.getToken();a.next();a.addCommand({domain:"core",keyword:"put",lino:b,value:e,target:c});return!0}a.warning("core:put: No such variable: '"+a.getToken()+"'")}return!1},run:function(a){var b=a[a.pc],e=a.getSymbolRecord(b.target);e.isValueHolder||a.variableDoesNotHoldAValueError(b.lino,e.name);a=a.evaluate(b.value);e.value[e.index]={type:a.type,numeric:a.numeric,content:a.content};e.imported&&(e=e.exporter.getSymbolRecord(e.exportedName),e.value[e.index]=
    50 a);return b.pc+1}},Replace:{compile:function(a){var b=a.getLino(),e=a.getNextValue();if(a.tokenIs("with")){var c=a.getNextValue();if(a.tokenIs("in")&&a.nextIsSymbol()){var d=a.getSymbolRecord();if(d.isValueHolder)return a.next(),a.addCommand({domain:"core",keyword:"replace",lino:b,original:e,replacement:c,target:d.name}),!0;throw Error("'"+d.name+"' does not hold a value");}}return!1},run:function(a){var b=a[a.pc],e=a.getValue(b.original),c=a.getValue(b.replacement),d=a.getSymbolRecord(b.target);
    51 a=a.getValue(d.value[d.index]).split(e).join(c);d.value[d.index]={type:"constant",numeric:!1,content:a};return b.pc+1}},Require:{compile:function(a){var b=a.getLino(),e=a.nextToken();if(["css","js"].includes(e)){var c=a.getNextValue();a.addCommand({domain:"core",keyword:"require",lino:b,type:e,url:c});return!0}throw Error("File type must be 'css' or 'js'");},run:function(a){var b=a[a.pc];a.require(b.type,a.getValue(b.url),function(){a.run(b.pc+1)});return 0}},Return:{compile:function(a){var b=a.getLino();
    52 a.next();a.addCommand({domain:"core",keyword:"return",lino:b});return!0},run:function(a){return a.stack.pop()}},Run:{compile:function(a){var b=a.getLino(),e=a.getNextValue(),c=[];if(a.tokenIs("with"))for(;;)if(a.nextIsSymbol(!0)){var d=a.getSymbolRecord();d.exporter=a.getProgram();c.push(d);a.next();if(!a.tokenIs("and"))break}if(a.tokenIs("as")&&a.nextIsSymbol(!0)){var l=a.getSymbolRecord();a.next();if("module"!==l.keyword)throw Error("'"+l.name+"' is not a module");l=l.name}var n=!1;a.tokenIs("nowait")&&
    53 (a.next(),n=!0);d=a.getPc();a.addCommand({domain:"core",keyword:"run",lino:b,script:e,imports:c,module:l,nowait:n,then:0});a.tokenIs("then")&&(b=a.getPc(),a.addCommand({domain:"core",keyword:"goto",goto:0}),a.getCommandAt(d).then=a.getPc(),a.next(),a.compileOne(!0),a.addCommand({domain:"core",keyword:"stop"}),a.getCommandAt(b).goto=a.getPc());return!0},run:function(a){a.nextPc=a.pc+1;a.runScript(a);return 0}},Sanitize:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var e=a.getToken();
    54 a.next();a.addCommand({domain:"core",keyword:"sanitize",lino:b,name:e});return!0}return!1},run:function(a){var b=a[a.pc];a=a.getSymbolRecord(b.name);a=a.value[a.index];a.content=JSON.stringify(JSON.parse(a.content));return b.pc+1}},Script:{compile:function(a){var b=a.getProgram();b.script=a.nextToken();EasyCoder.scripts[b.script]=b;a.next();return!0},run:function(a){return a[a.pc].pc+1}},Send:{compile:function(a){var b=a.getLino(),e="";a.nextTokenIs("to")||(e=a.getValue());if(a.tokenIs("to")){if(a.nextTokenIs("parent"))var c=
    55 "parent";else if(a.isSymbol){c=a.getSymbolRecord();if("module"!==c.keyword)throw Error("'"+c.name+"' is not a module");c=c.name}a.next();a.addCommand({domain:"core",keyword:"send",lino:b,message:e,recipient:c})}return!0},run:function(a){var b=a[a.pc],e=a.getValue(b.message);if("parent"===b.recipient){var c=a.parent;c&&a.parent.onMessage&&(c.message=e,c.run(c.onMessage))}else a=a.getSymbolRecord(b.recipient),a.program&&(a.program.message=e,a.program.run(a.program.onMessage));return b.pc+1}},Set:{compile:function(a){var b=
    56 a.getLino();if(a.nextIsSymbol()){var e=a.getSymbolRecord();if(!e.isValueHolder)return!1;if(a.nextTokenIs("to")){a.next();for(var c=[];;){a.mark();try{c.push(a.getValue())}catch(l){a.rewind();break}}a.addCommand({domain:"core",keyword:"set",lino:b,request:"setArray",target:e.name,value:c});return!0}a.addCommand({domain:"core",keyword:"set",lino:b,request:"setBoolean",target:e.name});return!0}switch(a.getToken()){case "ready":return a.next(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setReady"}),
    57 !0;case "element":e=a.getNextValue();if(a.tokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),"variable"===c.keyword&&a.nextTokenIs("to"))){var d=a.getNextValue();a.addCommand({domain:"core",keyword:"set",lino:b,request:"setElement",target:c.name,index:e,value:d});return!0}break;case "property":e=a.getNextValue();if(a.tokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),"variable"===c.keyword&&a.nextTokenIs("to")))return d=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setProperty",
    58 target:c.name,name:e,value:d}),!0;break;case "arg":if(e=a.getNextValue(),a.tokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),a.nextTokenIs("to")))return d=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setArg",target:c.name,name:e,value:d}),!0}a.tokenIs("the")&&a.next();switch(a.getToken()){case "elements":a.next();if(a.tokenIs("of")){a.next();if(!a.isSymbol())throw Error("Unknown variable '"+a.getToken()+"'");e=a.getToken();a.next();if(a.tokenIs("to"))return a.next(),
    59 c=a.getValue(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setElements",symbol:e,value:c}),!0}break;case "encoding":if(a.nextTokenIs("to"))return e=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",request:"encoding",lino:b,encoding:e}),!0;a.addWarning("Unknown encoding option");break;case "payload":if(a.nextTokenIs("of")&&a.nextIsSymbol()&&(e=a.getSymbolRecord(),"callback"===e.keyword&&a.nextTokenIs("to")))return c=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",
    60 request:"setPayload",lino:b,callback:e.name,payload:c}),!0}return!1},run:function(a){var b=a[a.pc];switch(b.request){case "setBoolean":var c=a.getSymbolRecord(b.target);c.isValueHolder?(c.value[c.index]={type:"boolean",content:!0},b.numeric=!1):a.variableDoesNotHoldAValueError(b.lino,c.name);break;case "setReady":a.parent.run(a.parent.nextPc);a.parent.nextPc=0;break;case "setArray":c=a.getSymbolRecord(b.target);c.elements=b.value.length;c.value=b.value;break;case "encoding":a.encoding=a.getValue(b.encoding);
    61 break;case "setElements":c=a.getSymbolRecord(b.symbol);var d=c.elements;c.elements=a.getValue(b.value);c.index=0;if(c.elements>d)for(a=d;a<c.elements;a++)c.value.push({}),c.element.push({});else c.value=c.value.slice(0,c.elements),c.element=c.element.slice(0,c.elements);break;case "setElement":c=a.getSymbolRecord(b.target);d=a.getValue(b.index);var f=JSON.parse(a.getValue(c.value[c.index]));a=a.getValue(b.value);f[d]=JSON.parse(a);c.value[c.index].content=JSON.stringify(f);break;case "setProperty":c=
    62 a.getSymbolRecord(b.target);(f=a.getValue(c.value[c.index]))||(f="{}");d="";try{d=JSON.parse(f)}catch(l){return a.runtimeError(b.lino,"Can't parse "+c.name),0}f=a.getValue(b.name);if(a=a.evaluate(b.value))a.content instanceof Array?d[f]=a.content:"boolean"===a.type?d[f]=a.content:a.numeric?d[f]=a.content:'{"'===a.content.substr(0,2)?d[f]=JSON.parse(a.content):d[f]=a.content.split('"').join('\\"'),c.value[c.index]={type:"constant",numeric:!1,content:JSON.stringify(d)};break;case "setPayload":a.getSymbolRecord(b.callback).payload=
    63 a.getValue(b.payload);break;case "setArg":d=a.getValue(b.name),c=a.getSymbolRecord(b.target),c[d]=a.getValue(b.value)}return b.pc+1}},Sort:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getSymbolRecord();if(a.nextTokenIs("with")){var d=a.nextToken();a.next();a.addCommand({domain:"core",keyword:"sort",lino:b,array:c.name,func:d});return!0}}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.array),d=c.value[c.index].content,f=a.getSymbolRecord(b.func).pc;try{var l=JSON.parse(d);
    64 l.sort(function(b,e){c.a=b;c.b=e;a.run(f);return c.v});c.value[c.index].content=JSON.stringify(l)}catch(n){a.runtimeError(b.lino,"Can't parse this array")}return b.pc+1}},Stop:{compile:function(a){var b=a.getLino();a.next();if(a.more()&&a.isSymbol()&&!a.getToken().endsWith(":")){var c=a.getSymbolRecord();return"module"===c.keyword?(a.next(),a.addCommand({domain:"core",keyword:"stop",lino:b,name:c.name}),!0):!1}a.addCommand({domain:"core",keyword:"stop",lino:b,next:0});return!0},run:function(a){var b=
    65 a[a.pc];if(b.name)a.getSymbolRecord(b.name).program.exit();else return 0;return b.pc+1}},Take:{compile:function(a){var b=a.getLino();a.next();var c=a.getValue();if(a.tokenIs("from"))if(a.next(),a.isSymbol()){var d=a.getSymbol();if(a.getCommandAt(d.pc).isValueHolder){if("giving"===a.peek()){d=a.getValue();a.next();var f=a.getToken();a.next();a.addCommand({domain:"core",keyword:"take",lino:b,value1:c,value2:d,target:f})}else d=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"take",lino:b,
    66 value1:c,target:d});return!0}a.warning("core "+g.name+": Expected value holder")}else{d=a.getValue();if(a.tokenIs("giving"))return a.next(),f=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"take",lino:b,value1:c,value2:d,target:f}),!0;a.warning("core "+g.name+': Expected "giving"')}return!1},run:function(a){var b=a[a.pc],c=b.value1,d=b.value2,f=a.getSymbolRecord(b.target);if(f.isValueHolder){var l=f.value[f.index];d?(a=a.getValue(d)-a.getValue(c),f.value[f.index]={type:"constant",numeric:!0,
    67 content:a}):(!l.numeric&&isNaN(l.content)&&a.nonNumericValueError(b.lino),a=parseInt(a.getValue(l))-parseInt(a.getValue(c)),f.value[f.index]={type:"constant",numeric:!0,content:a})}else a.variableDoesNotHoldAValueError(b.lino,f.name);return b.pc+1}},Toggle:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var c=a.getSymbolPc();a.next();a.addCommand({domain:"core",keyword:"toggle",lino:b,symbol:c});return!0}return!1},run:function(a){var b=a[a.pc],c=a[b.symbol];if(c.isValueHolder){var d=
    68 a.domain[c.domain];a=d.value.get(a,c.value[c.index]).content;d.value.put(c,{type:"boolean",content:!a})}else a.variableDoesNotHoldAValueError(b.lino,c.name);return b.pc+1}},Variable:{compile:function(a){a.compileVariable("core","variable",!0);return!0},run:function(a){return a[a.pc].pc+1}},Wait:{compile:function(a){var b=a.getLino();a.next();var c=a.getValue(a),d=1E3;switch(a.getToken()){case "milli":case "millis":a.next();d=1;break;case "tick":case "ticks":a.next();d=10;break;case "second":case "seconds":a.next();
    69 d=1E3;break;case "minute":case "minutes":a.next(),d=6E4}a.addCommand({domain:"core",keyword:"wait",lino:b,value:c,multiplier:d});return!0},run:function(a){var b=a[a.pc],c=a.getValue(b.value);setTimeout(function(){a.run(b.pc+1)},c*b.multiplier);return 0}},While:{compile:function(a){var b=a.getLino();a.next();var c=a.getCondition(),d=a.getPc();a.addCommand({domain:"core",keyword:"while",lino:b,condition:c});b=a.getPc();a.addCommand({domain:"core",keyword:"goto",goto:0});a.compileOne();a.addCommand({domain:"core",
    70 keyword:"goto",goto:d});a.getCommandAt(b).goto=a.getPc();return!0},run:function(a){return a.condition.test(a,a[a.pc].condition)?a.pc+2:a.pc+1}},getHandler:function(a){switch(a){case "add":return c.Add;case "alias":return c.Alias;case "append":return c.Append;case "begin":return c.Begin;case "callback":return c.Callback;case "clear":return c.Clear;case "close":return c.Close;case "debug":return c.Debug;case "decode":return c.Decode;case "divide":return c.Divide;case "dummy":return c.Dummy;case "encode":return c.Encode;
    71 case "end":return c.End;case "exit":return c.Exit;case "filter":return c.Filter;case "fork":return c.Fork;case "go":case "goto":return c.Go;case "gosub":return c.Gosub;case "if":return c.If;case "import":return c.Import;case "index":return c.Index;case "load":return c.Load;case "module":return c.Module;case "multiply":return c.Multiply;case "negate":return c.Negate;case "on":return c.On;case "print":return c.Print;case "put":return c.Put;case "replace":return c.Replace;case "require":return c.Require;
    72 case "return":return c.Return;case "run":return c.Run;case "sanitize":return c.Sanitize;case "script":return c.Script;case "send":return c.Send;case "set":return c.Set;case "sort":return c.Sort;case "stop":return c.Stop;case "take":return c.Take;case "toggle":return c.Toggle;case "variable":return c.Variable;case "wait":return c.Wait;case "while":return c.While;default:return!1}},run:function(a){var b=a[a.pc],e=c.getHandler(b.keyword);e||a.runtimeError(b.lino,"Unknown keyword '"+b.keyword+"' in 'core' package");
    73 return e.run(a)},isNegate:function(a){return"not"===a.getToken()?(a.next(),!0):!1},value:{compile:function(a){if(a.isSymbol()){var b=a.getToken();switch(a.getSymbolRecord().keyword){case "module":return a.next(),{domain:"core",type:"module",name:b};case "variable":var c=a.nextToken();return["format","modulo"].includes(c)?(a=a.getNextValue(),{domain:"core",type:c,name:b,value:a}):{domain:"core",type:"symbol",name:b}}return null}b=a.getToken();if("true"===b)return a.next(),{domain:"core",type:"boolean",
    74 content:!0};if("false"===b)return a.next(),{domain:"core",type:"boolean",content:!1};if("random"===b)return a.next(),{domain:"core",type:"random",range:a.getValue()};if("cos"===b)return a.next(),b=a.getValue(),a.skip("radius"),a=a.getValue(),{domain:"core",type:"cos",angle_c:b,radius_c:a};if("sin"===b)return a.next(),b=a.getValue(),a.skip("radius"),a=a.getValue(),{domain:"core",type:"sin",angle_s:b,radius_s:a};if("tan"===b)return a.next(),b=a.getValue(),a.skip("radius"),a=a.getValue(),{domain:"core",
    75 type:"tan",angle_t:b,radius_t:a};if(["now","today","newline","break","empty"].includes(b))return a.next(),{domain:"core",type:b};if("date"===b)return{domain:"core",type:"date",value:a.getNextValue()};if(["encode","decode","lowercase","hash"].includes(b))return a.next(),a=a.getValue(),{domain:"core",type:b,value:a};if("element"===b)return b=a.getNextValue(),a.tokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),a.next(),"variable"===c.keyword)?{domain:"core",type:"element",element:b,symbol:c.name}:
    76 null;if("property"===b)return b=a.getNextValue(),a.tokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),a.next(),"variable"===c.keyword)?{domain:"core",type:"property",property:b,symbol:c.name}:null;if("arg"===b&&(b=a.getNextValue(),a.tokenIs("of")&&a.nextIsSymbol()))return c=a.getSymbolRecord(),a.next(),{domain:"core",type:"arg",value:b,target:c.name};a.tokenIs("the")&&a.next();b=a.getToken();switch(b){case "elements":if(a.nextTokenIs("of")&&a.nextIsSymbol())return c=a.getToken(),a.next(),{domain:"core",
    77 type:b,name:c};break;case "index":if(a.nextTokenIs("of")){if(a.nextIsSymbol()){if("in"===a.peek())return b=a.getValue(),a=a.getNextValue(),{domain:"core",type:"indexOf",value1:b,value2:a};c=a.getToken();a.next();return{domain:"core",type:b,name:c}}b=a.getValue();if(a.tokenIs("in"))return a=a.getNextValue(),{domain:"core",type:"indexOf",value1:b,value2:a}}break;case "value":if(a.nextTokenIs("of"))return a.next(),{domain:"core",type:"valueOf",value:a.getValue()};break;case "length":if(a.nextTokenIs("of"))return a.next(),
    78 {domain:"core",type:"lengthOf",value:a.getValue()};break;case "left":case "right":try{if(c=a.getNextValue(),a.tokenIs("of")){var d=a.getNextValue();return{domain:"core",type:b,count:c,value:d}}}catch(f){}break;case "from":c=a.getNextValue();d=a.tokenIs("to")?a.getNextValue():null;if(a.tokenIs("of"))return a=a.getNextValue(),{domain:"core",type:b,from:c,to:d,value:a};break;case "position":if(a.nextTokenIs("of")&&(b=!1,a.nextTokenIs("the")&&a.nextTokenIs("last")&&(a.next(),b=!0),c=a.getValue(),a.tokenIs("in")))return a=
    79 a.getNextValue(),{domain:"core",type:"position",needle:c,haystack:a,last:b};break;case "payload":if(a.nextTokenIs("of")&&a.nextIsSymbol()&&(b=a.getSymbolRecord(),"callback"===b.keyword))return a.next(),{domain:"core",type:"payload",callback:b.name};break;case "message":case "error":return a.next(),{domain:"core",type:b}}return null},get:function(a,b){switch(b.type){case "boolean":return{type:"boolean",numeric:!1,content:b.content};case "elements":return{type:"constant",numeric:!0,content:a.getSymbolRecord(b.name).elements};
    80 case "index":return{type:"constant",numeric:!0,content:a.getSymbolRecord(b.name).index};case "random":return a=a.evaluate(b.range),{type:"constant",numeric:!0,content:Math.floor(Math.random()*a.content)};case "cos":var c=a.getValue(b.angle_c);a=a.getValue(b.radius_c);return{type:"constant",numeric:!0,content:parseInt(Math.cos(.01745329*parseFloat(c))*a,10)};case "sin":return c=a.getValue(b.angle_s),a=a.getValue(b.radius_s),{type:"constant",numeric:!0,content:parseInt(Math.sin(.01745329*parseFloat(c))*
    81 a,10)};case "tan":return c=a.getValue(b.angle_t),a=a.getValue(b.radius_t),{type:"constant",numeric:!0,content:parseInt(Math.tan(.01745329*parseFloat(c))*a,10)};case "valueOf":return a=parseInt(a.getValue(b.value)),{type:"constant",numeric:!0,content:a?a:0};case "lengthOf":return{type:"constant",numeric:!0,content:a.getValue(b.value).length};case "left":return{type:"constant",numeric:!1,content:a.getValue(b.value).substr(0,a.getValue(b.count))};case "right":return c=a.getValue(b.value),{type:"constant",
    82 numeric:!1,content:c.substr(c.length-a.getValue(b.count))};case "from":c=a.getValue(b.from);var d=b.to?a.getValue(b.to):null;a=a.getValue(b.value);return{type:"constant",numeric:!1,content:d?a.substr(c,d):a.substr(c)};case "position":return c=a.getValue(b.needle),a=a.getValue(b.haystack),{type:"constant",numeric:!0,content:b.last?a.lastIndexOf(c):a.indexOf(c)};case "payload":return{type:"constant",numeric:!1,content:a.getSymbolRecord(b.callback).payload};case "modulo":return c=a.getSymbolRecord(b.name),
    83 a=a.evaluate(b.value),{type:"constant",numeric:!0,content:c.value[c.index].content%a.content};case "format":c=a.getSymbolRecord(b.name);c=1E3*a.getValue(c.value[c.index]);try{switch(d=JSON.parse(a.getValue(b.value)),d.mode){case "time":return{type:"constant",numeric:!0,content:(new Date(c)).toLocaleTimeString(d.locale,d.options)};default:return{type:"constant",numeric:!0,content:(new Date(c)).toLocaleDateString(d.locale,d.options)}}}catch(f){a.runtimeError(a[a.pc].lino,"Can't parse "+b.value);break}case "empty":return{type:"constant",
    84 numeric:!1,content:""};case "now":return{type:"constant",numeric:!0,content:Math.floor(Date.now()/1E3)};case "today":return a=new Date,a.setHours(0,0,0,0),{type:"constant",numeric:!0,content:Math.floor(a.getTime()/1E3)};case "date":return{type:"constant",numeric:!0,content:Date.parse(a.getValue(b.value))/1E3};case "newline":return{type:"constant",numeric:!1,content:"\n"};case "break":return{type:"constant",numeric:!1,content:"<br />"};case "encode":return{type:"constant",numeric:!1,content:a.encode(a.getValue(b.value))};
    85 case "decode":return{type:"constant",numeric:!1,content:a.decode(a.getValue(b.value))};case "lowercase":return{type:"constant",numeric:!1,content:a.getValue(b.value).toLowerCase()};case "hash":a=a.getValue(b.value);b=0;if(0===a.length)return b;for(c=0;c<a.length;c++)d=a.charCodeAt(c),b=(b<<5)-b+d;return{type:"constant",numeric:!0,content:b};case "element":c=a.getValue(b.element);b=a.getSymbolRecord(b.symbol);d="";try{d=JSON.parse(a.getValue(b.value[b.index]))[c]}catch(f){a.runtimeError(a[a.pc].lino,
    86 "Can't parse JSON");break}return{type:"constant",numeric:!1,content:"object"===typeof d?JSON.stringify(d):d};case "property":d=a.getValue(b.property);b=a.getSymbolRecord(b.symbol);a=a.getValue(b.value[b.index]);c="";if(d&&a)if("object"===typeof a)c=a[d];else if("{"===a.charAt(0))try{c=JSON.parse(a)[d]}catch(f){console.log("Can't parse '"+a+"': "+f.message)}return{type:"constant",numeric:!isNaN(c),content:"object"===typeof c?JSON.stringify(c):c};case "module":return{type:"boolean",numeric:!1,content:a.getSymbolRecord(b.name).program};
    87 case "message":return c=a.message,{type:"constant",numeric:!1,content:c};case "error":return c=a.errorMessage,{type:"constant",numeric:!1,content:c};case "indexOf":d=a.getValue(b.value1);b=a.getValue(b.value2);try{return c=JSON.parse(b).indexOf(d),{type:"constant",numeric:!0,content:c}}catch(f){a.runtimeError(a[a.pc].lino,"Can't parse "+b)}break;case "arg":return c=a.getValue(b.value),c=a.getSymbolRecord(b.target)[c],{type:"constant",numeric:!isNaN(c),content:c}}return null},put:function(a,b){a.value[a.index]=
    88 b}},condition:{compile:function(a){if(a.isSymbol()){var b=a.getSymbolRecord();if("module"===b.keyword){if(a.nextTokenIs("is")){var d=!0;a.nextTokenIs("not")&&(a.next(),d=!1);if(a.tokenIs("running"))return a.next(),{domain:"core",type:"moduleRunning",name:b.name,sense:d}}return null}}if(a.tokenIs("not"))return{domain:"core",type:"not",value:a.getNextValue()};try{d=a.getValue();var g=a.getToken();if("includes"===g){var f=a.getNextValue();return{domain:"core",type:"includes",value1:d,value2:f}}if("is"===
    89 g){a.next();var l=c.isNegate(a);switch(a.getToken()){case "numeric":return a.next(),{domain:"core",type:"numeric",value1:d};case "even":return a.next(),{domain:"core",type:"even",value1:d};case "odd":return a.next(),{domain:"core",type:"odd",value1:d};case "greater":a.next();if(a.tokenIs("than")){a.next();var n=a.getValue();return{domain:"core",type:"greater",value1:d,value2:n,negate:l}}break;case "less":a.next();if(a.tokenIs("than")){a.next();var h=a.getValue();return{domain:"core",type:"less",value1:d,
    90 value2:h,negate:l}}break;default:var k=a.getValue();return{domain:"core",type:"is",value1:d,value2:k,negate:l}}}else if(d)return{domain:"core",type:"boolean",value:d}}catch(r){return a.warning("Can't get a value"),0}return null},test:function(a,b){switch(b.type){case "boolean":return a.getValue(b.value);case "numeric":return!isNaN(a.getValue(b.value1));case "even":return 0===a.getValue(b.value1)%2;case "odd":return 1===a.getValue(b.value1)%2;case "is":var c=a.compare(a,b.value1,b.value2);return b.negate?
    91 0!==c:0===c;case "greater":return c=a.compare(a,b.value1,b.value2),b.negate?0>=c:0<c;case "less":return c=a.compare(a,b.value1,b.value2),b.negate?0<=c:0>c;case "not":return!a.getValue(b.value);case "moduleRunning":return c=a.getSymbolRecord(b.name).program,b.sense?c:!c;case "includes":return c=JSON.parse(a.getValue(b.value1)),b=a.getValue(b.value2),c.includes(b)}return!1}}};k.exports=c},{}],6:[function(d,k,h){var g=this,c=d("./Compile"),a=d("./Run"),b=d("./Value"),e=d("./Condition"),q=d("./Compare"),
    92 f={domain:{core:d("./Core")},runtimeError:function(a,c){this.lino=a;this.reportError({message:"Line "+(0<=a?a:"")+": "+c},f.program);f.program.aborted=!0},nonNumericValueError:function(a){this.runtimeError(a,"Non-numeric value")},variableDoesNotHoldAValueError:function(a,c){this.runtimeError(a,"Variable '"+c+"' does not hold a value")},reportError:function(a,b,d){if(a.message)if(this.compiling||b){d=d?d:b.source;var e=d.tokens;d=d.scriptLines;e=this.compiling?e[c.getIndex()].lino:b[b.pc].lino;b=this.compiling?
    93 "Compile error":"Runtime error in '"+b.script+"'";b+=":\n";var l=e-5;for(l=0>l?0:l;l<e;l++){var n=(""+(l+1)).padStart(4," ");b+=n+" "+d[l].line.split("\\s").join(" ")+"\n"}b+=a.message+"\n";a=c.getWarnings();if(a.length)for(b+="Warnings:\n",a=$jscomp.makeIterator(a),d=a.next();!d.done;d=a.next())b+=d.value+"\n";console.log(b);alert(b)}else a="Error: "+a.message,alert(a),console.log(a);else console.log("An error occurred - origin was "+a.path[0])},getSymbolRecord:function(a){a=this[this.symbols[a].pc];
    94 return a.alias?this.getSymbolRecord(a.alias):a.exporter&&a.exporter!=this?a.exporter.getSymbolRecord(a.exportedName):a},verifySymbol:function(a){return this.symbols.hasOwnProperty(a)},encode:function(a){return b.encode(a,this.encoding)},decode:function(a){return b.decode(a,this.encoding)},evaluate:function(a){return b.evaluate(this,a)},getValue:function(a){return b.getValue(this,a)},getFormattedValue:function(a){a=b.evaluate(this,a);if(a.numeric)return a.content;if("boolean"===a.type)return a.content?
    95 "true":"false";if('{"'===a.content.substr(0,2)||"["===a.content[0])try{var c=JSON.parse(a.content);return JSON.stringify(c,null,2)}catch(p){return this.reportError(p),"{}"}return a.content},getSimpleValue:function(a){return!0===a||!1===a?{type:"boolean",content:a}:{type:"constant",numeric:Number.isInteger(a),content:a}},run:function(b){b&&(f.program=this,a.run(this,b))},exit:function(){a.exit(this)},register:function(a){f.program=a},require:function(a,b,c){var d=document.createElement("css"===a?"link":
    96 "script");switch(a){case "css":d.type="text/css";d.href=b;d.rel="stylesheet";break;case "js":d.type="text/javascript";d.src=b;break;default:return}d.onload=function(){console.log(Date.now()-f.timestamp+" ms: Library "+b+" loaded");c()};document.head.appendChild(d)},isUndefined:function(a){return"undefined"===typeof a},runScript:function(a){var b=a[a.pc],c=a.getValue(b.script),d=b.imports,e=b.module?a.getSymbolRecord(b.module):null;try{f.tokeniseAndCompile(c.split("\n"),d,e,this,b.then)}catch(u){this.reportError(u,
    97 f.program,a.source);a.onError?a.run(a.onError):a.parent&&a.parent.onError&&a.parent.run(a.parent.onError);return}b.nowait&&this.run(a.nextPc)},close:function(){},compileScript:function(a,d,g,h){var l=a.tokens;this.compiling=!0;c.value=b;c.condition=e;c.domain=f.domain;c.imports=d;d=c.compile(l);this.compiling=!1;d.EasyCoder=f;d.value=b;d.condition=e;d.compare=q;d.source=a;d.run=this.run;d.exit=this.exit;d.runScript=this.runScript;d.evaluate=this.evaluate;d.getValue=this.getValue;d.getFormattedValue=
    98 this.getFormattedValue;d.getSimpleValue=this.getSimpleValue;d.encode=this.encode;d.decode=this.decode;d.domain=this.domain;d.require=this.require;d.isUndefined=this.isUndefined;d.checkPlugin=this.checkPlugin;d.getPlugin=this.getPlugin;d.addLocalPlugin=this.addLocalPlugin;d.getPluginsPath=this.getPluginsPath;d.getSymbolRecord=this.getSymbolRecord;d.verifySymbol=this.verifySymbol;d.runtimeError=this.runtimeError;d.nonNumericValueError=this.nonNumericValueError;d.variableDoesNotHoldAValueError=this.variableDoesNotHoldAValueError;
    99 d.reportError=this.reportError;d.register=this.register;d.symbols=c.getSymbols();d.encoding="ec";d.popups=[];d.stack=[];d.queue=[0];d.module=g;d.parent=h;g&&(g.program=d);return d},tokeniseFile:function(a){var b=[],c=[],d=0;a.forEach(function(a,e){b.push({lino:e+1,line:a});for(var l=a.length,f="",g=!0,h=0;h<l;h++){var k=a[h];if(0==k.trim().length)g||(c.push({index:d,lino:e+1,token:f}),d++,f="",g=!0);else if(g=!1,"`"===k){for(m=h;++h<a.length&&"`"!==a[h];);f=a.substr(m,h-m+1)}else if("!"==k)break;
    100 else f+=k}0<f.length&&c.push({index:d,lino:e+1,token:f})});return{scriptLines:b,tokens:c}},tokeniseAndCompile:function(b,c,d,e,g){var l=null,h=Date.now();b=f.tokeniseFile(b);try{l=f.compileScript(b,c,d,e);var k=l.script?l.script:"<anon>",n=Date.now();console.log(n-f.timestamp+" ms: "+("Compiled "+k+": "+b.scriptLines.length+" lines ("+b.tokens.length+" tokens) in ")+(n-h+" ms"))}catch(w){"stop"!==w.message&&(c=f.program,this.reportError(w,c,b),c.onError&&c.run(c.onError))}l&&(l.onExit=g,l.running=
    101 !0,a.run(l,0))},tokenise:function(a){var b=a.split("\n");if(!g.tokenising){try{f.tokeniseAndCompile(b)}catch(p){f.reportError(p,null,a)}g.tokenising=!0}},setPluginCount:function(a){g.plugins=[];g.pluginCount=a},checkPlugin:function(a){return f.domain[a]},getPlugin:function(a,b,c){f.domain[a]?c():(a=document.createElement("script"),a.type="text/javascript",a.src=b+"?ver="+f.version,a.onload=function(){console.log(Date.now()-f.timestamp+" ms: Plugin "+b+" loaded");c()},document.head.appendChild(a))},
    102 addGlobalPlugin:function(a,b){g.plugins.push({name:a,handler:b});g.plugins.length===g.pluginCount&&(g.plugins.forEach(function(a){f.domain[a.name]=a.handler}),f.tokenise(g.source))},addLocalPlugin:function(a,b,c){f.domain[a]=b;c()},getPluginsPath:function(){return f.pluginsPath},loadPluginJs:function(a){console.log(Date.now()-f.timestamp+" ms: Load "+a+"/easycoder/plugins.js");var b=document.createElement("script");b.src=""+window.location.origin+a+"/easycoder/plugins.js?ver="+f.version;b.type="text/javascript";
    103 b.onload=function(){EasyCoder_Plugins.getGlobalPlugins(f.timestamp,a,f.setPluginCount,f.getPlugin,f.addGlobalPlugin)};b.onerror=function(){a?f.loadPluginJs(a.slice(0,a.lastIndexOf("/"))):f.reportError({message:"Can't load plugins.js"},f.program,g.source)};document.head.appendChild(b);f.pluginsPath=a},start:function(a){g.source=a;a=window.location.pathname;a=a.endsWith("/")?a.slice(0,-1):"";"undefined"===typeof EasyCoder_Plugins?f.loadPluginJs(a):(f.pluginsPath=a,EasyCoder_Plugins.getGlobalPlugins(f.timestamp,
    104 a,f.setPluginCount,f.getPlugin,f.addGlobalPlugin))}};k.exports=f},{"./Compare":2,"./Compile":3,"./Condition":4,"./Core":5,"./Run":7,"./Value":8}],7:[function(d,k,h){var g={run:function(c,a){var b=[],d=function(a){var b=9999;a.forEach(function(a){a=a.line;for(var c=0;c<a.length&&" "===a[c];)c++;0<c&&c<b&&(b=c)});return 0};if(b.length)b.push(a);else for(c.register(c),b.push(a);0<b.length;)for(c.pc=b.shift(),c.watchdog=0,a={};c.running;){if(1E6<c.watchdog){c.lino=c[c.pc].lino;c.reportError(Error("Program runaway intercepted.\nHave you forgotten to increment a loop counter?",
    105 c),c);break}c.watchdog++;var h=c[c.pc].domain;c.debugStep&&console.log(c.script+": Line "+c[c.pc].lino+": PC: "+c.pc+" "+h+":"+c[c.pc].keyword);var f=c.domain[h];if(!f){c.runtimeError(c[c.pc].lino,"Unknown domain '"+h+"'");break}c.pc=f.run(c);if(!c.pc)break;if(c.stop){c.tracing=!1;break}if(c.tracing){h=c[c.pc];f=c.source.scriptLines;var k=d(f),n=document.getElementById("easycoder-tracer");if(!n){c.runtimeError(h.lino,"Element 'easycoder-tracer' was not found");return}n.style.display="block";n.style.visibility=
    106 "visible";var p="";if(c.tracer){if(n=document.getElementById("easycoder-tracer-content")){c.tracer.variables.forEach(function(a,b,d){var e=c.getSymbolRecord(a);if(1<e.elements)for(p+=a+": "+e.index+"/"+e.elements+": ",a=0;a<e.elements;a++){var f=e.value[a];p=f?p+(f.content+" "):p+"undefined "}else p=(e=e.value[e.index])?p+(a+": "+e.content):p+(a+": undefined");switch(c.tracer.alignment){case "horizontal":b<d.length-1&&(p+=", ");break;case "vertical":p+="<br>"}});p+="<hr>";for(var t="",r=5;0<r;r--){if(h.lino){var u=
    107 f[h.lino-r].line.substr(k);t+='<input type="text" name="'+r+'"'+('value="'+(h.lino-r+1)+": "+u.split("\\s").join(" ")+'"')+'style="width:100%;border:none;enabled:false">'}t+="<br>"}n.innerHTML=p+" "+t;n.style.display="block";a.run=document.getElementById("easycoder-run-button");a.step=document.getElementById("easycoder-step-button");a.run.onclick=function(a){return function(){a.run.blur();c.tracing=!1;document.getElementById("easycoder-tracer-content").style.display="none";try{g.run(c,c.resume)}catch(v){var b=
    108 "Error in run handler: "+v.message;console.log(b);alert(b)}}}(a);a.step.onclick=function(a){return function(){console.log("step");a.step.blur();c.tracing=!0;document.getElementById("easycoder-tracer-content").style.display="block";try{c.run(c.resume)}catch(v){var b="Error in step handler: "+v.message;console.log(b);alert(b)}}}(a)}c.resume=c.pc;c.pc=0}break}a={run:a.run,step:a.step}}},exit:function(c){c.onExit&&(c.parent.run(c.onExit),c.module.program=null,c.running=!1)}};k.exports=g},{}],8:[function(d,
    109 k,h){var g={getItem:function(c){var a=c.getToken();if(!a)return null;if("true"===a)return c.next(),{type:"boolean",content:!0};if("false"===a)return c.next(),{type:"boolean",content:!1};if("`"===a.charAt(0))return c.next(),{type:"constant",numeric:!1,content:a.substring(1,a.length-1)};if(a.charAt(0).match(/[0-9-]/)){var b=eval(a);if(Number.isInteger(b))return c.next(),{type:"constant",numeric:!0,content:b};throw Error("'"+a+"' is not an integer");}a=c.getIndex();b=$jscomp.makeIterator(Object.keys(c.domain));
    110 for(var d=b.next();!d.done;d=b.next())if(d=d.value,c.rewindTo(a),d=c.domain[d].value.compile(c))return d;return null},compile:function(c){var a=c.getToken(),b=g.getItem(c);if(!b)throw Error("Undefined value: '"+a+"'");if("cat"===c.getToken()){for(a={type:"cat",numeric:!1,parts:[b]};c.tokenIs("cat");)c.next(),a.parts.push(c.value.getItem(c));return a}return b},doValue:function(c,a){if("undefined"===typeof a.type)return c.runtimeError(c[c.pc].lino,"Undefined value (variable not initialized?)"),null;
    111 switch(a.type){case "cat":return{type:"constant",numeric:!1,content:a.parts.reduce(function(a,b){return a+g.doValue(c,b).content},"")};case "boolean":case "constant":return a;case "symbol":var b=c.getSymbolRecord(a.name);if(b.isValueHolder){if(a=b.value[b.index]){b=a.content;if(null===b||"undefined"===typeof b)a.content=a.numeric?0:"";return a}return null}return c.domain[b.domain].value.get(c,a)}return c.domain[a.domain].value.get(c,a)},constant:function(c,a){return{type:"constant",numeric:a,content:c}},
    112 evaluate:function(c,a){if(!a)return{type:"constant",numeric:!1,content:""};var b=g.doValue(c,a);if(b)return b;c.runtimeError(c[c.pc].lino,"Can't decode value: "+a)},getValue:function(c,a){return g.evaluate(c,a).content},encode:function(c,a){if(c)switch(a){case "ec":return c.replace(/'/g,"~sq~").replace(/"/g,"~dq~").replace(/\n/g,"%0a").replace(/\r/g,"%0d");case "url":return encodeURIComponent(c.replace(/\s/g,"+"));case "sanitize":return c.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}return c},
    113 decode:function(c,a){if(c)switch(a){case "ec":return c.replace(/~dq~/g,'"').replace(/~sq~/g,"'").replace(/%0a/g,"\n").replace(/%0d/g,"\r");case "url":return decodeURIComponent(c).replace(/\+/g," ")}return c}};k.exports=g},{}]},{},[1]);
     1var $jscomp$this=this,$jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}};$jscomp.arrayIterator=function(a){return{next:$jscomp.arrayIteratorImpl(a)}};$jscomp.makeIterator=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):$jscomp.arrayIterator(a)};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;
     2$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
     3$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.SymbolClass=function(a,b){this.$jscomp$symbol$id_=a;$jscomp.defineProperty(this,"description",{configurable:!0,writable:!0,value:b})};$jscomp.SymbolClass.prototype.toString=function(){return this.$jscomp$symbol$id_};
     4$jscomp.Symbol=function(){function a(c){if(this instanceof a)throw new TypeError("Symbol is not a constructor");return new $jscomp.SymbolClass($jscomp.SYMBOL_PREFIX+(c||"")+"_"+b++,c)}var b=0;return a}();
     5$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("Symbol.iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.iteratorPrototype($jscomp.arrayIteratorImpl(this))}});$jscomp.initSymbolIterator=function(){}};
     6$jscomp.initSymbolAsyncIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.asyncIterator;a||(a=$jscomp.global.Symbol.asyncIterator=$jscomp.global.Symbol("Symbol.asyncIterator"));$jscomp.initSymbolAsyncIterator=function(){}};$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};
     7$jscomp.iteratorFromArray=function(a,b){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var c=0,d={next:function(){if(c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d.next=function(){return{done:!0,value:void 0}};return d.next()}};d[Symbol.iterator]=function(){return d};return d};
     8$jscomp.polyfill=function(a,b,c,d){if(b){c=$jscomp.global;a=a.split(".");for(d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})}};$jscomp.polyfill("Array.prototype.keys",function(a){return a?a:function(){return $jscomp.iteratorFromArray(this,function(a){return a})}},"es6","es3");
     9$jscomp.checkStringArgs=function(a,b,c){if(null==a)throw new TypeError("The 'this' value for String.prototype."+c+" must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype."+c+" must not be a regular expression");return a+""};
     10$jscomp.polyfill("String.prototype.endsWith",function(a){return a?a:function(a,c){var b=$jscomp.checkStringArgs(this,a,"endsWith");a+="";void 0===c&&(c=b.length);c=Math.max(0,Math.min(c|0,b.length));for(var e=a.length;0<e&&0<c;)if(b[--c]!=a[--e])return!1;return 0>=e}},"es6","es3");$jscomp.polyfill("Object.is",function(a){return a?a:function(a,c){return a===c?0!==a||1/a===1/c:a!==a&&c!==c}},"es6","es3");
     11$jscomp.polyfill("Array.prototype.includes",function(a){return a?a:function(a,c){var b=this;b instanceof String&&(b=String(b));var e=b.length;c=c||0;for(0>c&&(c=Math.max(c+e,0));c<e;c++){var f=b[c];if(f===a||Object.is(f,a))return!0}return!1}},"es7","es3");$jscomp.polyfill("String.prototype.includes",function(a){return a?a:function(a,c){return-1!==$jscomp.checkStringArgs(this,a,"includes").indexOf(a,c||0)}},"es6","es3");
     12$jscomp.polyfill("Math.trunc",function(a){return a?a:function(a){a=Number(a);if(isNaN(a)||Infinity===a||-Infinity===a||0===a)return a;var b=Math.floor(Math.abs(a));return 0>a?-b:b}},"es6","es3");$jscomp.polyfill("String.prototype.repeat",function(a){return a?a:function(a){var b=$jscomp.checkStringArgs(this,null,"repeat");if(0>a||1342177279<a)throw new RangeError("Invalid count value");a|=0;for(var d="";a;)if(a&1&&(d+=b),a>>>=1)b+=b;return d}},"es6","es3");
     13$jscomp.stringPadding=function(a,b){a=void 0!==a?String(a):" ";return 0<b&&a?a.repeat(Math.ceil(b/a.length)).substring(0,b):""};$jscomp.polyfill("String.prototype.padStart",function(a){return a?a:function(a,c){var b=$jscomp.checkStringArgs(this,null,"padStart");return $jscomp.stringPadding(c,a-b.length)+b}},"es8","es3");$jscomp.polyfill("Number.isFinite",function(a){return a?a:function(a){return"number"!==typeof a?!1:!isNaN(a)&&Infinity!==a&&-Infinity!==a}},"es6","es3");
     14$jscomp.polyfill("Number.isInteger",function(a){return a?a:function(a){return Number.isFinite(a)?a===Math.floor(a):!1}},"es6","es3");
     15var EasyCoder_Compare=function(a,b,c){b=a.value.evaluate(a,b);a=a.value.evaluate(a,c);c=b.content;var d=a.content;c&&b.numeric?a.numeric||(d="undefined"===typeof d?0:parseInt(d)):(d&&a.numeric&&(d=d.toString()),"undefined"===typeof c&&(c=""),"undefined"===typeof d&&(d=""));return c>d?1:c<d?-1:0},EasyCoder_Compiler={name:"EasyCoder_Compiler",getTokens:function(){return this.tokens},addWarning:function(a){this.warnings.push(a)},warning:function(a){this.addWarning(a)},unrecognisedSymbol:function(a){this.addWarning("Unrecognised symbol '"+
     16a+"'")},getWarnings:function(){return this.warnings},getIndex:function(){return this.index},next:function(a){this.index+=void 0===a?1:a},peek:function(){return this.tokens[this.index+1].token},more:function(){return this.index<this.tokens.length},getToken:function(){return this.index>=this.tokens.length?null:this.tokens[this.index]?this.tokens[this.index].token:null},nextToken:function(){this.next();return this.getToken()},tokenIs:function(a){return this.index>=this.tokens.length?!1:a===this.tokens[this.index].token},
     17nextTokenIs:function(a){this.next();return this.tokenIs(a)},skip:function(a){if(this.index>=this.tokens.length)return null;this.next();this.tokenIs(a)&&this.next()},prev:function(){this.index--},getLino:function(){return this.index>=this.tokens.length?0:this.tokens[this.index].lino},getTarget:function(a){a=void 0===a?this.index:a;return this.tokens[a].token},getTargetPc:function(a){a=void 0===a?this.index:a;return this.symbols[this.getTarget(a)].pc},getCommandAt:function(a){return this.program[a]},
     18isSymbol:function(a){a=void 0===a?!1:a;if(this.getTarget()in this.symbols)return!0;if(a)throw Error("Unknown symbol: '"+this.getTarget()+"'");return!1},nextIsSymbol:function(a){a=void 0===a?!1:a;this.next();return this.isSymbol(a)},getSymbol:function(a){if(this.isSymbol(void 0===a?!1:a))return this.symbols[this.getToken()]},getSymbolPc:function(a){return this.getSymbol(void 0===a?!1:a).pc},getSymbolRecord:function(){var a=this.program[this.getSymbolPc(!0)];a.used=!0;return a},getSymbols:function(){return this.symbols},
     19getProgram:function(){return this.program},getPc:function(){return this.program.length},getValue:function(){return this.value.compile(this)},getNextValue:function(){this.next();return this.getValue()},getCondition:function(){return this.condition.compile(this)},constant:function(a,b){return this.value.constant(a,void 0===b?!1:b)},addCommand:function(a){this.program.push(Object.assign({},{pc:this.program.length},a))},addSymbol:function(a,b){this.symbols[a]={pc:b}},mark:function(){this.savedMark=this.index},
     20rewind:function(){this.index=this.savedMark},rewindTo:function(a){this.index=a},completeHandler:function(){var a=this.getLino(),b=this.getPc();this.addCommand({domain:"core",keyword:"goto",lino:a,goto:0});this.compileOne();this.addCommand({domain:"core",keyword:"stop",lino:a,next:0});this.getCommandAt(b).goto=this.getPc();return!0},compileVariable:function(a,b,c,d){c=void 0===c?!1:c;d=void 0===d?null:d;this.next();var e=this.getLino(),f=this.getTokens()[this.getIndex()];if(this.symbols[f.token])throw Error("Duplicate variable name '"+
     21f.token+"'");var g=this.getPc();this.next();this.addSymbol(f.token,g);a={domain:a,keyword:b,lino:e,isSymbol:!0,used:!1,isValueHolder:c,name:f.token,elements:1,index:0,value:[{}],element:[],extra:d};"dom"===d&&(a.element=[]);this.addCommand(a);return a},compileToken:function(){var a=this.getToken();if(a){this.mark();for(var b=$jscomp.makeIterator(Object.keys(this.domain)),c=b.next();!c.done;c=b.next()){if((c=this.domain[c.value])&&(c=c.getHandler(a))&&c.compile(this))return;this.rewind()}console.log("No handler found");
     22throw Error("I don't understand '"+a+"...'");}},compileOne:function(){var a=this.getToken();if(a){this.warnings=[];var b=this.program.length;if(a.endsWith(":")){a=a.substring(0,a.length-1);if(this.symbols[a])throw Error("Duplicate symbol: '"+a+"'");this.symbols[a]={pc:b};this.index++}else this.compileToken()}},compileFromHere:function(a){for(;this.index<this.tokens.length;){var b=this.tokens[this.index].token;if("else"===b)return this.program;this.compileOne();if(-1<a.indexOf(b))break}},compile:function(a){this.tokens=
     23a;this.index=0;this.program=[];this.program.symbols={};this.symbols=this.program.symbols;this.warnings=[];this.compileFromHere([]);this.addCommand({domain:"core",keyword:"exit",lino:this.getLino(),next:0});for(var b in this.symbols)a=this.program[this.symbols[b].pc],!a.isSymbol||a.used||a.exporter||console.log("Symbol '"+a.name+"' has not been used.");return this.program}},EasyCoder_Condition={name:"EasyCoder_Condition",compile:function(a){a.mark();for(var b=$jscomp.makeIterator(Object.keys(a.domain)),
     24c=b.next();!c.done;c=b.next()){if(c=a.domain[c.value].condition.compile(a))return Object.assign({},{domain:name},c);a.rewind()}},test:function(a,b){return a.domain[b.domain].condition.test(a,b)}},EasyCoder_Core={name:"EasyCoder_Core",Add:{compile:function(a){var b=a.getLino();a.next();var c=a.getValue();if(a.tokenIs("to"))if(a.next(),a.isSymbol()){var d=a.getSymbol();if(a.getCommandAt(d.pc).isValueHolder){if("giving"===a.peek()){d=a.getValue();a.next();var e=a.getToken();a.next();a.addCommand({domain:"core",
     25keyword:"add",lino:b,value1:c,value2:d,target:e})}else d=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"add",lino:b,value1:c,target:d});return!0}a.warning("core 'add': Expected value holder")}else{d=a.getValue();if(a.tokenIs("giving"))return a.next(),e=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"add",lino:b,value1:c,value2:d,target:e}),!0;a.warning("core 'add'': Expected \"giving\"")}return!1},run:function(a){var b=a[a.pc],c=b.value1,d=b.value2,e=a.getSymbolRecord(b.target);
     26if(e.isValueHolder){var f=e.value[e.index];d?(a=a.getValue(d)+a.getValue(c),e.value[e.index]={type:"constant",numeric:!0,content:a}):(!f.numeric&&isNaN(f.content)&&a.nonNumericValueError(b.lino),a=parseInt(f.content)+parseInt(a.getValue(c)),e.value[e.index]={type:"constant",numeric:!0,content:a})}else a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},Alias:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var c=a.getToken();a.next();if(a.tokenIs("to")&&(a.next(),a.isSymbol())){var d=
     27a.getSymbolRecord();d.used=!0;a.next();a.addCommand({domain:"core",keyword:"alias",lino:b,alias:c,symbol:d.name});return!0}}return!1},run:function(a){var b=a[a.pc],c=a.symbols[b.alias].pc,d=a[c],e=a.getSymbolRecord(b.symbol);a[c]={pc:d.pc,domain:e.domain,keyword:e.keyword,lino:d.lino,name:d.name,alias:b.symbol};return b.pc+1}},Append:{compile:function(a){var b=a.getLino(),c=a.getNextValue();if(a.tokenIs("to")&&a.nextIsSymbol()){var d=a.getSymbolRecord();if(d.isValueHolder)return a.next(),a.addCommand({domain:"core",
     28keyword:"append",lino:b,value:c,select:d.name}),!0}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.select);try{var d=a.getValue(b.value),e=["{","["].includes(d[0])?JSON.parse(d):d,f=c.value[c.index],g=f.content;g=g?JSON.parse(g):[];g.push(e);f.content=JSON.stringify(g);return b.pc+1}catch(k){return a.runtimeError(b.lino,"JSON: Unable to parse value"),!1}}},Begin:{compile:function(a){a.next();a.compileFromHere(["end"]);return!0},run:function(a){return a[a.pc].pc+1}},Callback:{compile:function(a){a.compileVariable("core",
     29"callback");return!0},run:function(a){return a[a.pc].pc+1}},Clear:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var c=a.getSymbolRecord();if(c.isValueHolder)return c=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"clear",lino:b,symbol:c}),!0;a.warning("'Variable '"+c.name+"' does not hold a value")}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.symbol);c.isValueHolder?(a.domain[c.domain].value.put(c,{type:"boolean",content:!1}),b.numeric=!1):a.variableDoesNotHoldAValueError(b.lino,
     30c.name);return b.pc+1}},Close:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getSymbolRecord();if("module"===c.keyword)return a.next(),a.addCommand({domain:"core",keyword:"close",lino:b,module:c.name}),!0}return!1},run:function(a){var b=a[a.pc];a=a.getSymbolRecord(b.module).program;a.run(a.onClose);return b.pc+1}},Debug:{compile:function(a){var b=a.getLino();if(a.nextTokenIs("program")){a.next();if(["item","pc"].includes(a.getToken())){var c=a.getNextValue();a.addCommand({domain:"core",
     31keyword:"debug",lino:b,item:c});return!0}a.addCommand({domain:"core",keyword:"debug",lino:b,item:"program"});return!0}return a.tokenIs("symbols")?(a.next(),a.addCommand({domain:"core",keyword:"debug",lino:b,item:"symbols"}),!0):a.tokenIs("symbol")?(c=a.nextToken(),a.next(),a.addCommand({domain:"core",keyword:"debug",lino:b,item:"symbol",name:c}),!0):a.tokenIs("step")?(a.next(),a.addCommand({domain:"core",keyword:"debug",lino:b,item:"step"}),!0):!1},run:function(a){var b=a[a.pc],c=b.item;switch(c){case "symbols":console.log("Symbols: "+
     32JSON.stringify(a.symbols,null,2));break;case "symbol":a=a.getSymbolRecord(b.name);c=a.exporter.script;delete a.exporter;console.log("Symbol: "+JSON.stringify(a,null,2));a.exporter.script=c;break;case "step":a.debugStep=!0;break;case "program":console.log("Debug program: "+JSON.stringify(a,null,2));break;default:0<=c.content&&console.log("Debug item "+c.content+": "+JSON.stringify(a[c.content],null,2))}return b.pc+1}},Decode:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getToken();
     33a.next();a.addCommand({domain:"core",keyword:"decode",lino:b,symbol:c});return!0}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.symbol);if(c.isValueHolder){var d=a.getValue(c.value[c.index]);c.value[c.index]={type:"constant",numeric:!1,content:a.decode(d)};b.numeric=!1}else a.variableDoesNotHoldAValueError(b.lino,c.name);return b.pc+1}},Divide:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getSymbol();var d=a.getCommandAt(c.pc).name}c=a.getValue();a.tokenIs("by")&&
     34a.next();var e=a.getValue();if(a.tokenIs("giving")){a.next();if(a.isSymbol())return d=a.getSymbol(),d=a.getCommandAt(d.pc).name,a.next(),a.addCommand({domain:"core",keyword:"divide",lino:b,value1:c,value2:e,target:d}),!0;a.warning("core 'divide'': Expected value holder")}else return"undefined"===typeof d&&a.warning("core 'divide': No target variable given"),a.addCommand({domain:"core",keyword:"divide",lino:b,value2:e,target:d}),!0;return!1},run:function(a){var b=a[a.pc],c=b.value1,d=b.value2,e=a.getSymbolRecord(b.target);
     35if(e.isValueHolder){var f=e.value[e.index];c?(a=a.getValue(c)/a.getValue(d),e.value[e.index]={type:"constant",numeric:!0,content:Math.trunc(a)}):(!f.numeric&&isNaN(f.content)&&a.nonNumericValueError(b,lino),a=parseInt(f.content)/parseInt(a.getValue(d)),e.value[e.index]={type:"constant",numeric:!0,content:Math.trunc(a)})}else a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},Dummy:{compile:function(a){var b=a.getLino();a.next();a.addCommand({domain:"core",keyword:"dummy",lino:b});return!0},
     36run:function(a){return a[a.pc].pc+1}},Encode:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var c=a.getToken();a.next();a.addCommand({domain:"core",keyword:"encode",lino:b,symbol:c});return!0}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.symbol);if(c.isValueHolder){var d=a.getValue(c.value[c.index]);c.value[c.index]={type:"constant",numeric:!1,content:a.encode(d)};b.numeric=!1}else a.variableDoesNotHoldAValueError(b.lino,c.name);return b.pc+1}},End:{compile:function(a){a.next();
     37return!0},run:function(){return 0}},Exit:{compile:function(a){a.next();a.addCommand({domain:"core",keyword:"exit"});return!0},run:function(a){a.parent.run(a.parent.nextPc);a.parent.nextPc=0;a.exit();return 0}},Filter:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getSymbolRecord();if(a.nextTokenIs("with")){var d=a.nextToken();a.next();a.addCommand({domain:"core",keyword:"filter",lino:b,array:c.name,func:d});return!0}}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.array),
     38d=c.value[c.index].content,e=a.getSymbolRecord(b.func).pc;try{var f=JSON.parse(d).filter(function(b){c.a=b;a.run(e);return c.v});c.value[c.index].content=JSON.stringify(f)}catch(g){a.runtimeError(b.lino,"Can't parse this array")}return b.pc+1}},Fork:{compile:function(a){var b=a.getLino();a.next();a.nextTokenIs("to")&&a.next();var c=a.getToken();a.next();a.addCommand({domain:"core",keyword:"fork",lino:b,label:c});return!0},run:function(a){var b=a[a.pc];try{a.run(a.symbols[b.label].pc)}catch(c){console.log(c.message),
     39alert(c.message)}return b.pc+1}},Go:{compile:function(a){var b=a.getLino();a.nextTokenIs("to")&&a.next();var c=a.getToken();a.next();a.addCommand({domain:"core",keyword:"go",lino:b,label:c});return!0},run:function(a){var b=a[a.pc];if(b.label){if(a.verifySymbol(b.label)){var c=a.symbols[b.label];if(c)return c.pc}a.runtimeError(b.lino,"Unknown symbol '"+b.label+"'");return 0}return b.goto}},Gosub:{compile:function(a){var b=a.getLino();a.nextTokenIs("to")&&a.next();var c=a.getToken();a.next();a.addCommand({domain:"core",
     40keyword:"gosub",lino:b,label:c});return!0},run:function(a){var b=a[a.pc];if(a.verifySymbol(b.label))return a.stack.push(a.pc+1),a.symbols[b.label].pc;a.runtimeError(b.lino,"Unknown symbol '"+b.label+"'");return 0}},If:{compile:function(a){var b=a.getLino();a.next();var c=a.condition.compile(a),d=a.getPc();a.addCommand({domain:"core",keyword:"if",lino:b,condition:c});a.compileOne();if(!a.getToken())return a.getCommandAt(d).else=a.getPc(),!0;a.tokenIs("else")?(c=a.getPc(),a.addCommand({domain:"core",
     41keyword:"goto",lino:b,goto:0}),a.getCommandAt(d).else=a.getPc(),a.next(),a.compileOne(!0),a.getCommandAt(c).goto=a.getPc()):a.getCommandAt(d).else=a.getPc();return!0},run:function(a){var b=a[a.pc];return a.condition.test(a,b.condition)?b.pc+1:b.else}},Import:{compile:function(a){var b=a.imports,c=EasyCoder.scripts[b.caller],d=a.getProgram();if(b.length){b=$jscomp.makeIterator(b);for(var e=b.next();!e.done;e=b.next()){e=c.getSymbolRecord(e.value);var f=a.nextToken(),g=e.keyword;if(f===g){if(f=a.compileVariable(e.domain,
     42g,!0),f=d[a.getSymbols()[f.name].pc],f.element=e.element,f.exporter=e.exporter?e.exporter:c.script,f.exportedName=e.name,f.extra=e.extra,f.isValueHolder=e.isValueHolder,e.program&&(f.program=e.program),f.imported=!0,!a.tokenIs("and"))break}else throw Error("Mismatched import variable type for '"+e.name+"'");}if(a.tokenIs("and"))throw Error("Imports do not match exports");}else a.next();return!0},run:function(a){return a[a.pc].pc+1}},Index:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol(!0)){var c=
     43a.getToken();if(a.nextTokenIs("to")){var d=a.getNextValue();a.addCommand({domain:"core",keyword:"index",lino:b,symbol:c,value:d});return!0}}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.symbol),d=a.getValue(b.value);d>=c.elements&&a.runtimeError(b.lino,"Array index "+d+" is out of range for '"+c.name+"'");c.index=d;c.imported&&(EasyCoder.symbols[c.exporter].getSymbolRecord(c.exportedName).index=d);return b.pc+1}},Load:{compile:function(a){var b=a.getLino();switch(a.nextToken()){case "plugin":var c=
     44a.getNextValue();a.addCommand({domain:"core",keyword:"load",lino:b,name:c});return!0}return!1},run:function(a){var b=a[a.pc],c=a.getValue(b.name);switch(b.keyword){case "load":if(a.checkPlugin(c))return b.pc+1;EasyCoder_Plugins.getLocalPlugin(a.getPluginsPath,c,a.getPlugin,a.addLocalPlugin,function(){a.run(b.pc+1)});return 0}}},Module:{compile:function(a){a.compileVariable("core","module");return!0},run:function(a){return a[a.pc].pc+1}},Multiply:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var c=
     45a.getSymbol();var d=a.getCommandAt(c.pc).name}c=a.getValue();a.tokenIs("by")&&a.next();var e=a.getValue();if(a.tokenIs("giving")){a.next();if(a.isSymbol())return d=a.getSymbol(),d=a.getCommandAt(d.pc).name,a.next(),a.addCommand({domain:"core",keyword:"multiply",lino:b,value1:c,value2:e,target:d}),!0;a.warning("core multiply: Expected value holder")}else return"undefined"===typeof d&&a.warning("core multiply: No target variable given"),a.addCommand({domain:"core",keyword:"multiply",lino:b,value2:e,
     46target:d}),!0;return!1},run:function(a){var b=a[a.pc],c=b.value1,d=b.value2,e=a.getSymbolRecord(b.target);if(e.isValueHolder){var f=e.value[e.index];c?(a=a.getValue(c)*a.getValue(d),e.value[e.index]={type:"constant",numeric:!0,content:a}):(!f.numeric&&isNaN(f.content)&&a.nonNumericValueError(b,lino),a=parseInt(f.content)*parseInt(a.getValue(d)),e.value[e.index]={type:"constant",numeric:!0,content:a})}else a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},Negate:{compile:function(a){var b=
     47a.getLino();a.next();if(a.isSymbol()){var c=a.getToken();a.next();a.addCommand({domain:"core",keyword:"negate",lino:b,symbol:c});return!0}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.symbol);c.isValueHolder?c.value[c.index]={type:"constant",numeric:!0,content:-c.value[c.index].content}:a.variableDoesNotHoldAValueError(b.lino,c.name);return b.pc+1}},On:{compile:function(a){var b=a.getLino(),c=a.nextToken();switch(c){case "close":case "message":case "error":return a.next(),a.addCommand({domain:"core",
     48keyword:"on",lino:b,action:c}),a.completeHandler()}return a.isSymbol()&&(c=a.getSymbolRecord(),"callback"===c.keyword)?(a.next(),a.addCommand({domain:"core",keyword:"on",lino:b,action:c.name}),a.completeHandler()):!1},run:function(a){var b=a[a.pc],c=b.pc+2;switch(b.action){case "close":a.onClose=c;break;case "message":a.onMessage=c;break;case "error":a.onError=c;break;default:var d=a.getSymbolRecord(b.action);if(d)d.cb=c;else return a.runtimeError(b.lino,"Unknown action '"+b.action+"'"),0}return b.pc+
     491}},Print:{compile:function(a){var b=a.getLino();a.next();var c=a.getValue();a.addCommand({domain:"core",keyword:"print",lino:b,value:c});return!0},run:function(a){var b=a[a.pc];a=a.getFormattedValue(b.value);console.log("-> "+a);return b.pc+1}},Put:{compile:function(a){var b=a.getLino(),c=a.getNextValue();if(a.tokenIs("into")){if(a.nextIsSymbol()){var d=a.getToken();a.next();a.addCommand({domain:"core",keyword:"put",lino:b,value:c,target:d});return!0}a.warning("core:put: No such variable: '"+a.getToken()+
     50"'")}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.target);c.isValueHolder||a.variableDoesNotHoldAValueError(b.lino,c.name);a=a.evaluate(b.value);c.value[c.index]={type:a.type,numeric:a.numeric,content:a.content};c.imported&&(c=EasyCoder.scripts[c.exporter].getSymbolRecord(c.exportedName),c.value[c.index]=a);return b.pc+1}},Replace:{compile:function(a){var b=a.getLino(),c=a.getNextValue();if(a.tokenIs("with")){var d=a.getNextValue();if(a.tokenIs("in")&&a.nextIsSymbol()){var e=a.getSymbolRecord();
     51if(e.isValueHolder)return a.next(),a.addCommand({domain:"core",keyword:"replace",lino:b,original:c,replacement:d,target:e.name}),!0;throw Error("'"+e.name+"' does not hold a value");}}return!1},run:function(a){var b=a[a.pc],c=a.getValue(b.original),d=a.getValue(b.replacement),e=a.getSymbolRecord(b.target);a=a.getValue(e.value[e.index]).split(c).join(d);e.value[e.index]={type:"constant",numeric:!1,content:a};return b.pc+1}},Require:{compile:function(a){var b=a.getLino(),c=a.nextToken();if(["css","js"].includes(c)){var d=
     52a.getNextValue();a.addCommand({domain:"core",keyword:"require",lino:b,type:c,url:d});return!0}throw Error("File type must be 'css' or 'js'");},run:function(a){var b=a[a.pc];a.require(b.type,a.getValue(b.url),function(){a.run(b.pc+1)});return 0}},Return:{compile:function(a){var b=a.getLino();a.next();a.addCommand({domain:"core",keyword:"return",lino:b});return!0},run:function(a){return a.stack.pop()}},Run:{compile:function(a){var b=a.getLino(),c=a.getNextValue(),d=a.getProgram(),e=[];if(a.tokenIs("with"))for(;;)if(a.nextIsSymbol(!0)){var f=
     53a.getSymbolRecord();e.push(f.name);a.next();if(!a.tokenIs("and"))break}if(a.tokenIs("as")&&a.nextIsSymbol(!0)){var g=a.getSymbolRecord();g.program=d;a.next();if("module"!==g.keyword)throw Error("'"+g.name+"' is not a module");g=g.name}f=!1;a.tokenIs("nowait")&&(a.next(),f=!0);d=a.getPc();a.addCommand({domain:"core",keyword:"run",lino:b,script:c,imports:e,module:g,nowait:f,then:0});a.tokenIs("then")&&(b=a.getPc(),a.addCommand({domain:"core",keyword:"goto",goto:0}),a.getCommandAt(d).then=a.getPc(),
     54a.next(),a.compileOne(!0),a.addCommand({domain:"core",keyword:"stop"}),a.getCommandAt(b).goto=a.getPc());return!0},run:function(a){a.nextPc=a.pc+1;a.runScript(a);return 0}},Sanitize:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getToken();a.next();a.addCommand({domain:"core",keyword:"sanitize",lino:b,name:c});return!0}return!1},run:function(a){var b=a[a.pc];a=a.getSymbolRecord(b.name);a=a.value[a.index];a.content=JSON.stringify(JSON.parse(a.content));return b.pc+1}},Script:{compile:function(a){var b=
     55a.getProgram();b.script=a.nextToken();if(EasyCoder.scripts[b.script])throw Error("Script '"+b.script+"' is already running.");EasyCoder.scripts[b.script]=b;a.next();return!0},run:function(a){return a[a.pc].pc+1}},Send:{compile:function(a){var b=a.getLino(),c="";a.nextTokenIs("to")||(c=a.getValue());if(a.tokenIs("to")){if(a.nextTokenIs("parent"))var d="parent";else if(a.isSymbol){d=a.getSymbolRecord();if("module"!==d.keyword)throw Error("'"+d.name+"' is not a module");d=d.name}a.next();a.addCommand({domain:"core",
     56keyword:"send",lino:b,message:c,recipient:d})}return!0},run:function(a){var b=a[a.pc],c=a.getValue(b.message);if("parent"===b.recipient){var d=a.parent;d&&a.parent.onMessage&&(d.message=c,d.run(d.onMessage))}else a=a.getSymbolRecord(b.recipient),a.program&&(a.program.message=c,a.program.run(a.program.onMessage));return b.pc+1}},Set:{compile:function(a){var b=a.getLino();if(a.nextIsSymbol()){var c=a.getSymbolRecord();if(!c.isValueHolder)return!1;if(a.nextTokenIs("to")){a.next();for(var d=[];;){a.mark();
     57try{d.push(a.getValue())}catch(f){a.rewind();break}}a.addCommand({domain:"core",keyword:"set",lino:b,request:"setArray",target:c.name,value:d});return!0}a.addCommand({domain:"core",keyword:"set",lino:b,request:"setBoolean",target:c.name});return!0}switch(a.getToken()){case "ready":return a.next(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setReady"}),!0;case "element":c=a.getNextValue();if(a.tokenIs("of")&&a.nextIsSymbol()&&(d=a.getSymbolRecord(),"variable"===d.keyword&&a.nextTokenIs("to"))){var e=
     58a.getNextValue();a.addCommand({domain:"core",keyword:"set",lino:b,request:"setElement",target:d.name,index:c,value:e});return!0}break;case "property":c=a.getNextValue();if(a.tokenIs("of")&&a.nextIsSymbol()&&(d=a.getSymbolRecord(),"variable"===d.keyword&&a.nextTokenIs("to")))return e=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setProperty",target:d.name,name:c,value:e}),!0;break;case "arg":if(c=a.getNextValue(),a.tokenIs("of")&&a.nextIsSymbol()&&(d=a.getSymbolRecord(),
     59a.nextTokenIs("to")))return e=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setArg",target:d.name,name:c,value:e}),!0}a.tokenIs("the")&&a.next();switch(a.getToken()){case "elements":a.next();if(a.tokenIs("of")){a.next();if(!a.isSymbol())throw Error("Unknown variable '"+a.getToken()+"'");c=a.getToken();a.next();if(a.tokenIs("to"))return a.next(),d=a.getValue(),a.addCommand({domain:"core",keyword:"set",lino:b,request:"setElements",symbol:c,value:d}),!0}break;case "encoding":if(a.nextTokenIs("to"))return c=
     60a.getNextValue(),a.addCommand({domain:"core",keyword:"set",request:"encoding",lino:b,encoding:c}),!0;a.addWarning("Unknown encoding option");break;case "payload":if(a.nextTokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),"callback"===c.keyword&&a.nextTokenIs("to")))return d=a.getNextValue(),a.addCommand({domain:"core",keyword:"set",request:"setPayload",lino:b,callback:c.name,payload:d}),!0}return!1},run:function(a){var b=a[a.pc];switch(b.request){case "setBoolean":var c=a.getSymbolRecord(b.target);
     61c.isValueHolder?(c.value[c.index]={type:"boolean",content:!0},b.numeric=!1):a.variableDoesNotHoldAValueError(b.lino,c.name);break;case "setReady":a.parent.run(a.parent.nextPc);a.parent.nextPc=0;break;case "setArray":c=a.getSymbolRecord(b.target);c.elements=b.value.length;c.value=b.value;break;case "encoding":a.encoding=a.getValue(b.encoding);break;case "setElements":c=a.getSymbolRecord(b.symbol);var d=c.elements;c.elements=a.getValue(b.value);c.index=0;if(c.elements>d)for(a=d;a<c.elements;a++)c.value.push({}),
     62c.element.push({});else c.value=c.value.slice(0,c.elements),c.element=c.element.slice(0,c.elements);break;case "setElement":c=a.getSymbolRecord(b.target);d=a.getValue(b.index);var e=JSON.parse(a.getValue(c.value[c.index]));a=a.getValue(b.value);e[d]=JSON.parse(a);c.value[c.index].content=JSON.stringify(e);break;case "setProperty":c=a.getSymbolRecord(b.target);(e=a.getValue(c.value[c.index]))||(e="{}");d="";try{d=JSON.parse(e)}catch(f){return a.runtimeError(b.lino,"Can't parse "+c.name),0}e=a.getValue(b.name);
     63if(a=a.evaluate(b.value))a.content instanceof Array?d[e]=a.content:"boolean"===a.type?d[e]=a.content:a.numeric?d[e]=a.content:'{"'===a.content.substr(0,2)?d[e]=JSON.parse(a.content):d[e]=a.content.split('"').join('\\"'),c.value[c.index]={type:"constant",numeric:!1,content:JSON.stringify(d)};break;case "setPayload":a.getSymbolRecord(b.callback).payload=a.getValue(b.payload);break;case "setArg":d=a.getValue(b.name),c=a.getSymbolRecord(b.target),c[d]=a.getValue(b.value)}return b.pc+1}},Sort:{compile:function(a){var b=
     64a.getLino();if(a.nextIsSymbol()){var c=a.getSymbolRecord();if(a.nextTokenIs("with")){var d=a.nextToken();a.next();a.addCommand({domain:"core",keyword:"sort",lino:b,array:c.name,func:d});return!0}}return!1},run:function(a){var b=a[a.pc],c=a.getSymbolRecord(b.array),d=c.value[c.index].content,e=a.getSymbolRecord(b.func).pc;try{var f=JSON.parse(d);f.sort(function(b,d){c.a=b;c.b=d;a.run(e);return c.v});c.value[c.index].content=JSON.stringify(f)}catch(g){a.runtimeError(b.lino,"Can't parse this array")}return b.pc+
     651}},Split:{compile:function(a){var b=a.getLino();item=a.getNextValue();var c="\n";a.tokenIs("on")&&(c=a.getNextValue());if(["giving","into"].includes(a.getToken())&&a.nextIsSymbol()){var d=a.getSymbolRecord();if("variable"===d.keyword)return a.next(),a.addCommand({domain:"core",keyword:"split",lino:b,item:item,on:c,target:d.name}),!0}return!1},run:function(a){var b=a[a.pc],c=a.getValue(b.item),d=a.getValue(b.on);c=c.split(d);d=c.length;targetRecord=a.getSymbolRecord(b.target);targetRecord.elements=
     66d;for(a=0;a<d;a++)targetRecord.value[a]={type:"constant",numeric:!1,content:c[a]};targetRecord.index=0;return b.pc+1}},Stop:{compile:function(a){var b=a.getLino();a.next();if(a.more()&&a.isSymbol()&&!a.getToken().endsWith(":")){var c=a.getSymbolRecord();return"module"===c.keyword?(a.next(),a.addCommand({domain:"core",keyword:"stop",lino:b,name:c.name}),!0):!1}a.addCommand({domain:"core",keyword:"stop",lino:b,next:0});return!0},run:function(a){var b=a[a.pc];if(b.name)a.getSymbolRecord(b.name).program.exit();
     67else return 0;return b.pc+1}},Take:{compile:function(a){var b=a.getLino();a.next();var c=a.getValue();if(a.tokenIs("from"))if(a.next(),a.isSymbol()){var d=a.getSymbol();if(a.getCommandAt(d.pc).isValueHolder){if("giving"===a.peek()){d=a.getValue();a.next();var e=a.getToken();a.next();a.addCommand({domain:"core",keyword:"take",lino:b,value1:c,value2:d,target:e})}else d=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"take",lino:b,value1:c,target:d});return!0}a.warning("core 'take'': Expected value holder")}else{d=
     68a.getValue();if(a.tokenIs("giving"))return a.next(),e=a.getToken(),a.next(),a.addCommand({domain:"core",keyword:"take",lino:b,value1:c,value2:d,target:e}),!0;a.warning("core 'take'': Expected \"giving\"")}return!1},run:function(a){var b=a[a.pc],c=b.value1,d=b.value2,e=a.getSymbolRecord(b.target);if(e.isValueHolder){var f=e.value[e.index];d?(a=a.getValue(d)-a.getValue(c),e.value[e.index]={type:"constant",numeric:!0,content:a}):(!f.numeric&&isNaN(f.content)&&a.nonNumericValueError(b.lino),a=parseInt(a.getValue(f))-
     69parseInt(a.getValue(c)),e.value[e.index]={type:"constant",numeric:!0,content:a})}else a.variableDoesNotHoldAValueError(b.lino,e.name);return b.pc+1}},Toggle:{compile:function(a){var b=a.getLino();a.next();if(a.isSymbol()){var c=a.getSymbolPc();a.next();a.addCommand({domain:"core",keyword:"toggle",lino:b,symbol:c});return!0}return!1},run:function(a){var b=a[a.pc],c=a[b.symbol];if(c.isValueHolder){var d=a.domain[c.domain];a=d.value.get(a,c.value[c.index]).content;d.value.put(c,{type:"boolean",content:!a})}else a.variableDoesNotHoldAValueError(b.lino,
     70c.name);return b.pc+1}},Variable:{compile:function(a){a.compileVariable("core","variable",!0);return!0},run:function(a){return a[a.pc].pc+1}},Wait:{compile:function(a){var b=a.getLino();a.next();var c=a.getValue(a),d=1E3;switch(a.getToken()){case "milli":case "millis":a.next();d=1;break;case "tick":case "ticks":a.next();d=10;break;case "second":case "seconds":a.next();d=1E3;break;case "minute":case "minutes":a.next(),d=6E4}a.addCommand({domain:"core",keyword:"wait",lino:b,value:c,multiplier:d});return!0},
     71run:function(a){var b=a[a.pc],c=a.getValue(b.value);setTimeout(function(){a.run(b.pc+1)},c*b.multiplier);return 0}},While:{compile:function(a){var b=a.getLino();a.next();var c=a.getCondition(),d=a.getPc();a.addCommand({domain:"core",keyword:"while",lino:b,condition:c});b=a.getPc();a.addCommand({domain:"core",keyword:"goto",goto:0});a.compileOne();a.addCommand({domain:"core",keyword:"goto",goto:d});a.getCommandAt(b).goto=a.getPc();return!0},run:function(a){return a.condition.test(a,a[a.pc].condition)?
     72a.pc+2:a.pc+1}},getHandler:function(a){switch(a){case "add":return EasyCoder_Core.Add;case "alias":return EasyCoder_Core.Alias;case "append":return EasyCoder_Core.Append;case "begin":return EasyCoder_Core.Begin;case "callback":return EasyCoder_Core.Callback;case "clear":return EasyCoder_Core.Clear;case "close":return EasyCoder_Core.Close;case "debug":return EasyCoder_Core.Debug;case "decode":return EasyCoder_Core.Decode;case "divide":return EasyCoder_Core.Divide;case "dummy":return EasyCoder_Core.Dummy;
     73case "encode":return EasyCoder_Core.Encode;case "end":return EasyCoder_Core.End;case "exit":return EasyCoder_Core.Exit;case "filter":return EasyCoder_Core.Filter;case "fork":return EasyCoder_Core.Fork;case "go":case "goto":return EasyCoder_Core.Go;case "gosub":return EasyCoder_Core.Gosub;case "if":return EasyCoder_Core.If;case "import":return EasyCoder_Core.Import;case "index":return EasyCoder_Core.Index;case "load":return EasyCoder_Core.Load;case "module":return EasyCoder_Core.Module;case "multiply":return EasyCoder_Core.Multiply;
     74case "negate":return EasyCoder_Core.Negate;case "on":return EasyCoder_Core.On;case "print":return EasyCoder_Core.Print;case "put":return EasyCoder_Core.Put;case "replace":return EasyCoder_Core.Replace;case "require":return EasyCoder_Core.Require;case "return":return EasyCoder_Core.Return;case "run":return EasyCoder_Core.Run;case "sanitize":return EasyCoder_Core.Sanitize;case "script":return EasyCoder_Core.Script;case "send":return EasyCoder_Core.Send;case "set":return EasyCoder_Core.Set;case "sort":return EasyCoder_Core.Sort;
     75case "split":return EasyCoder_Core.Split;case "stop":return EasyCoder_Core.Stop;case "take":return EasyCoder_Core.Take;case "toggle":return EasyCoder_Core.Toggle;case "variable":return EasyCoder_Core.Variable;case "wait":return EasyCoder_Core.Wait;case "while":return EasyCoder_Core.While;default:return!1}},run:function(a){var b=a[a.pc],c=EasyCoder_Core.getHandler(b.keyword);c||a.runtimeError(b.lino,"Unknown keyword '"+b.keyword+"' in 'core' package");return c.run(a)},isNegate:function(a){return"not"===
     76a.getToken()?(a.next(),!0):!1},value:{compile:function(a){if(a.isSymbol()){var b=a.getToken();switch(a.getSymbolRecord().keyword){case "module":return a.next(),{domain:"core",type:"module",name:b};case "variable":var c=a.nextToken();return["format","modulo"].includes(c)?(a=a.getNextValue(),{domain:"core",type:c,name:b,value:a}):{domain:"core",type:"symbol",name:b}}return null}b=a.getToken();if("true"===b)return a.next(),{domain:"core",type:"boolean",content:!0};if("false"===b)return a.next(),{domain:"core",
     77type:"boolean",content:!1};if("random"===b)return a.next(),{domain:"core",type:"random",range:a.getValue()};if("cos"===b)return a.next(),b=a.getValue(),a.skip("radius"),a=a.getValue(),{domain:"core",type:"cos",angle_c:b,radius_c:a};if("sin"===b)return a.next(),b=a.getValue(),a.skip("radius"),a=a.getValue(),{domain:"core",type:"sin",angle_s:b,radius_s:a};if("tan"===b)return a.next(),b=a.getValue(),a.skip("radius"),a=a.getValue(),{domain:"core",type:"tan",angle_t:b,radius_t:a};if(["now","today","newline",
     78"break","empty"].includes(b))return a.next(),{domain:"core",type:b};if("date"===b)return{domain:"core",type:"date",value:a.getNextValue()};if(["encode","decode","lowercase","hash"].includes(b))return a.next(),a=a.getValue(),{domain:"core",type:b,value:a};if("element"===b)return b=a.getNextValue(),a.tokenIs("of")&&a.nextIsSymbol()&&(c=a.getSymbolRecord(),a.next(),"variable"===c.keyword)?{domain:"core",type:"element",element:b,symbol:c.name}:null;if("property"===b)return b=a.getNextValue(),a.tokenIs("of")&&
     79a.nextIsSymbol()&&(c=a.getSymbolRecord(),a.next(),"variable"===c.keyword)?{domain:"core",type:"property",property:b,symbol:c.name}:null;if("arg"===b){var d=a.getNextValue();if(a.tokenIs("of")&&a.nextIsSymbol())return b=a.getSymbolRecord(),a.next(),{domain:"core",type:"arg",value:d,target:b.name}}if(["character","char"].includes(b)&&(b=a.getNextValue(),a.tokenIs("of")))return a=a.getNextValue(),{domain:"core",type:"char",index:b,value:a};a.tokenIs("the")&&a.next();b=a.getToken();switch(b){case "elements":if(a.nextTokenIs("of")&&
     80a.nextIsSymbol())return c=a.getToken(),a.next(),{domain:"core",type:b,name:c};break;case "index":if(a.nextTokenIs("of")){if(a.nextIsSymbol()){if("in"===a.peek())return b=a.getValue(),a=a.getNextValue(),{domain:"core",type:"indexOf",value1:b,value2:a};c=a.getToken();a.next();return{domain:"core",type:b,name:c}}b=a.getValue();if(a.tokenIs("in"))return a=a.getNextValue(),{domain:"core",type:"indexOf",value1:b,value2:a}}break;case "value":if(a.nextTokenIs("of"))return a.next(),{domain:"core",type:"valueOf",
     81value:a.getValue()};break;case "length":if(a.nextTokenIs("of"))return a.next(),{domain:"core",type:"lengthOf",value:a.getValue()};break;case "left":case "right":try{if(c=a.getNextValue(),a.tokenIs("of")){var e=a.getNextValue();return{domain:"core",type:b,count:c,value:e}}}catch(f){}break;case "from":c=a.getNextValue();e=a.tokenIs("to")?a.getNextValue():null;if(a.tokenIs("of"))return a=a.getNextValue(),{domain:"core",type:b,from:c,to:e,value:a};break;case "position":b=!1;a.nextTokenIs("nocase")&&(b=
     82!0,a.next());if(a.tokenIs("of")&&(c=!1,a.nextTokenIs("the")&&a.nextTokenIs("last")&&(a.next(),c=!0),e=a.getValue(),a.tokenIs("in")))return a=a.getNextValue(),{domain:"core",type:"position",needle:e,haystack:a,last:c,nocase:b};break;case "payload":if(a.nextTokenIs("of")&&a.nextIsSymbol()&&(b=a.getSymbolRecord(),"callback"===b.keyword))return a.next(),{domain:"core",type:"payload",callback:b.name};break;case "message":case "error":return a.next(),{domain:"core",type:b}}return null},get:function(a,b){switch(b.type){case "boolean":return{type:"boolean",
     83numeric:!1,content:b.content};case "elements":return{type:"constant",numeric:!0,content:a.getSymbolRecord(b.name).elements};case "index":return{type:"constant",numeric:!0,content:a.getSymbolRecord(b.name).index};case "random":return a=a.evaluate(b.range),{type:"constant",numeric:!0,content:Math.floor(Math.random()*a.content)};case "cos":var c=a.getValue(b.angle_c);a=a.getValue(b.radius_c);return{type:"constant",numeric:!0,content:parseInt(Math.cos(.01745329*parseFloat(c))*a,10)};case "sin":return c=
     84a.getValue(b.angle_s),a=a.getValue(b.radius_s),{type:"constant",numeric:!0,content:parseInt(Math.sin(.01745329*parseFloat(c))*a,10)};case "tan":return c=a.getValue(b.angle_t),a=a.getValue(b.radius_t),{type:"constant",numeric:!0,content:parseInt(Math.tan(.01745329*parseFloat(c))*a,10)};case "valueOf":return a=parseInt(a.getValue(b.value)),{type:"constant",numeric:!0,content:a?a:0};case "lengthOf":return{type:"constant",numeric:!0,content:a.getValue(b.value).length};case "left":return{type:"constant",
     85numeric:!1,content:a.getValue(b.value).substr(0,a.getValue(b.count))};case "right":return c=a.getValue(b.value),{type:"constant",numeric:!1,content:c.substr(c.length-a.getValue(b.count))};case "from":c=a.getValue(b.from);var d=b.to?a.getValue(b.to):null;a=a.getValue(b.value);return{type:"constant",numeric:!1,content:d?a.substr(c,d):a.substr(c)};case "position":return c=a.getValue(b.needle),a=a.getValue(b.haystack),b.nocase&&(c=c.toLowerCase(),a=a.toLowerCase()),{type:"constant",numeric:!0,content:b.last?
     86a.lastIndexOf(c):a.indexOf(c)};case "payload":return{type:"constant",numeric:!1,content:a.getSymbolRecord(b.callback).payload};case "modulo":return c=a.getSymbolRecord(b.name),a=a.evaluate(b.value),{type:"constant",numeric:!0,content:c.value[c.index].content%a.content};case "format":c=a.getSymbolRecord(b.name);c=1E3*a.getValue(c.value[c.index]);try{switch(d=JSON.parse(a.getValue(b.value)),d.mode){case "time":return{type:"constant",numeric:!0,content:(new Date(c)).toLocaleTimeString(d.locale,d.options)};
     87default:var e=new Date(c);return{type:"constant",numeric:!0,content:"iso"===d.format?e.getFullYear()+"-"+(e.getMonth()+1)+"-"+e.getDate():e.toLocaleDateString(d.locale,d.options)}}}catch(f){a.runtimeError(a[a.pc].lino,"Can't parse "+b.value);break}case "empty":return{type:"constant",numeric:!1,content:""};case "now":return{type:"constant",numeric:!0,content:Math.floor(Date.now()/1E3)};case "today":return a=new Date,a.setHours(0,0,0,0),{type:"constant",numeric:!0,content:Math.floor(a.getTime()/1E3)};
     88case "date":c=Date.parse(a.getValue(b.value))/1E3;if(isNaN(c)){a.runtimeError(a[a.pc].lino,"Invalid date format; expecting 'yyyy-mm-dd'");break}return{type:"constant",numeric:!0,content:c};case "newline":return{type:"constant",numeric:!1,content:"\n"};case "break":return{type:"constant",numeric:!1,content:"<br />"};case "encode":return{type:"constant",numeric:!1,content:a.encode(a.getValue(b.value))};case "decode":return{type:"constant",numeric:!1,content:a.decode(a.getValue(b.value))};case "lowercase":return{type:"constant",
     89numeric:!1,content:a.getValue(b.value).toLowerCase()};case "hash":a=a.getValue(b.value);b=0;if(0===a.length)return b;for(c=0;c<a.length;c++)d=a.charCodeAt(c),b=(b<<5)-b+d;return{type:"constant",numeric:!0,content:b};case "element":c=a.getValue(b.element);b=a.getSymbolRecord(b.symbol);d="";try{d=JSON.parse(a.getValue(b.value[b.index]))[c]}catch(f){a.runtimeError(a[a.pc].lino,"Can't parse JSON");break}return{type:"constant",numeric:!1,content:"object"===typeof d?JSON.stringify(d):d};case "property":d=
     90a.getValue(b.property);b=a.getSymbolRecord(b.symbol);a=a.getValue(b.value[b.index]);c="";if(d&&a)if("object"===typeof a)c=a[d];else if("{"===a.charAt(0))try{c=JSON.parse(a)[d]}catch(f){console.log("Can't parse '"+a+"': "+f.message)}return{type:"constant",numeric:!isNaN(c),content:"object"===typeof c?JSON.stringify(c):c};case "module":return{type:"boolean",numeric:!1,content:a.getSymbolRecord(b.name).program};case "message":return c=a.message,{type:"constant",numeric:!1,content:c};case "error":return c=
     91a.errorMessage,{type:"constant",numeric:!1,content:c};case "indexOf":d=a.getValue(b.value1);b=a.getValue(b.value2);try{return c=JSON.parse(b).indexOf(d),{type:"constant",numeric:!0,content:c}}catch(f){a.runtimeError(a[a.pc].lino,"Can't parse "+b)}break;case "arg":return c=a.getValue(b.value),c=a.getSymbolRecord(b.target)[c],{type:"constant",numeric:!isNaN(c),content:c};case "char":return c=a.getValue(b.index),{type:"constant",numeric:!1,content:a.getValue(b.value)[c]}}return null},put:function(a,
     92b){a.value[a.index]=b}},condition:{compile:function(a){if(a.isSymbol()){var b=a.getSymbolRecord();if("module"===b.keyword){if(a.nextTokenIs("is")){var c=!0;a.nextTokenIs("not")&&(a.next(),c=!1);if(a.tokenIs("running"))return a.next(),{domain:"core",type:"moduleRunning",name:b.name,sense:c}}return null}}if(a.tokenIs("not"))return{domain:"core",type:"not",value:a.getNextValue()};try{c=a.getValue();var d=a.getToken();if("includes"===d){var e=a.getNextValue();return{domain:"core",type:"includes",value1:c,
     93value2:e}}if("is"===d){a.next();var f=EasyCoder_Core.isNegate(a);switch(a.getToken()){case "numeric":return a.next(),{domain:"core",type:"numeric",value1:c,negate:f};case "even":return a.next(),{domain:"core",type:"even",value1:c};case "odd":return a.next(),{domain:"core",type:"odd",value1:c};case "greater":a.next();if(a.tokenIs("than")){a.next();var g=a.getValue();return{domain:"core",type:"greater",value1:c,value2:g,negate:f}}break;case "less":a.next();if(a.tokenIs("than")){a.next();var k=a.getValue();
     94return{domain:"core",type:"less",value1:c,value2:k,negate:f}}break;default:var h=a.getValue();return{domain:"core",type:"is",value1:c,value2:h,negate:f}}}else if(c)return{domain:"core",type:"boolean",value:c}}catch(l){return a.warning("Can't get a value"),0}return null},test:function(a,b){switch(b.type){case "boolean":return a.getValue(b.value);case "numeric":var c=a.getValue(b.value1);c=" "===c||isNaN(c);return b.negate?c:!c;case "even":return 0===a.getValue(b.value1)%2;case "odd":return 1===a.getValue(b.value1)%
     952;case "is":return c=a.compare(a,b.value1,b.value2),b.negate?0!==c:0===c;case "greater":return c=a.compare(a,b.value1,b.value2),b.negate?0>=c:0<c;case "less":return c=a.compare(a,b.value1,b.value2),b.negate?0<=c:0>c;case "not":return!a.getValue(b.value);case "moduleRunning":return c=a.getSymbolRecord(b.name).program,b.sense?c:!c;case "includes":return c=JSON.parse(a.getValue(b.value1)),b=a.getValue(b.value2),c.includes(b)}return!1}}},EasyCoder={name:"EasyCoder_Main",domain:{core:EasyCoder_Core},runtimeError:function(a,
     96b){this.lino=a;this.reportError({message:"Line "+(0<=a?a:"")+": "+b},this.program);this.program.aborted=!0},nonNumericValueError:function(a){this.runtimeError(a,"Non-numeric value")},variableDoesNotHoldAValueError:function(a,b){this.runtimeError(a,"Variable '"+b+"' does not hold a value")},reportError:function(a,b,c){if(a.message)if(this.compiling||b){c=c?c:b.source;var d=c.tokens;c=c.scriptLines;d=this.compiling?d[EasyCoder_Compiler.getIndex()].lino:b[b.pc].lino;b=this.compiling?"Compile error":
     97"Runtime error in '"+b.script+"'";b+=":\n";var e=d-5;for(e=0>e?0:e;e<d;e++){var f=(""+(e+1)).padStart(4," ");b+=f+" "+c[e].line.split("\\s").join(" ")+"\n"}b+=a.message+"\n";a=EasyCoder_Compiler.getWarnings();if(a.length)for(b+="Warnings:\n",a=$jscomp.makeIterator(a),c=a.next();!c.done;c=a.next())b+=c.value+"\n";console.log(b);alert(b)}else a="Error: "+a.message,alert(a),console.log(a);else console.log("An error occurred - origin was "+a.path[0])},getSymbolRecord:function(a){a=this[this.symbols[a].pc];
     98return a.alias?this.getSymbolRecord(a.alias):a.exporter?EasyCoder.scripts[a.exporter].getSymbolRecord(a.exportedName):a},verifySymbol:function(a){return this.symbols.hasOwnProperty(a)},encode:function(a){return EasyCoder_Value.encode(a,this.encoding)},decode:function(a){return EasyCoder_Value.decode(a,this.encoding)},evaluate:function(a){return EasyCoder_Value.evaluate(this,a)},getValue:function(a){return EasyCoder_Value.getValue(this,a)},getFormattedValue:function(a){a=EasyCoder_Value.evaluate(this,
     99a);if(a.numeric)return a.content;if("boolean"===a.type)return a.content?"true":"false";if("undefined"!==typeof a.content&&2<=a.content.length&&('{"'===a.content.substr(0,2)||"["===a.content[0]))try{var b=JSON.parse(a.content);return JSON.stringify(b,null,2)}catch(c){return this.reportError(c),"{}"}return a.content},getSimpleValue:function(a){return!0===a||!1===a?{type:"boolean",content:a}:{type:"constant",numeric:Number.isInteger(a),content:a}},run:function(a){a&&(this.program=this,EasyCoder_Run.run(this,
     100a))},exit:function(){EasyCoder_Run.exit(this)},register:function(a){$jscomp$this.program=a},require:function(a,b,c){var d=document.createElement("css"===a?"link":"script");switch(a){case "css":d.type="text/css";d.href=b;d.rel="stylesheet";break;case "js":d.type="text/javascript";d.src=b;break;default:return}d.onload=function(){console.log(Date.now()-EasyCoder.timestamp+" ms: Library "+b+" loaded");c()};document.head.appendChild(d)},isUndefined:function(a){return"undefined"===typeof a},runScript:function(a){var b=
     101a[a.pc],c=a.getValue(b.script),d=b.imports;d.caller=a.script;var e=b.module?a.getSymbolRecord(b.module):null;try{EasyCoder.tokeniseAndCompile(c.split("\n"),d,e,this,b.then)}catch(f){EasyCoder.reportError(f,a,a.source);a.onError?a.run(a.onError):(a=a.parent)&&a.onError&&a.run(a.onError);return}b.nowait&&EasyCoder.run(a.nextPc)},close:function(){},compileScript:function(a,b,c,d){var e=a.tokens;this.compiling=!0;var f=EasyCoder_Compiler;this.compiler=f;f.value=EasyCoder_Value;f.condition=EasyCoder_Condition;
     102f.domain=this.domain;f.imports=b;b=EasyCoder_Compiler.compile(e);this.compiling=!1;b.EasyCoder=this;b.value=EasyCoder_Value;b.condition=EasyCoder_Condition;b.compare=EasyCoder_Compare;b.source=a;b.run=this.run;b.exit=this.exit;b.runScript=this.runScript;b.evaluate=this.evaluate;b.getValue=this.getValue;b.getFormattedValue=this.getFormattedValue;b.getSimpleValue=this.getSimpleValue;b.encode=this.encode;b.decode=this.decode;b.domain=this.domain;b.require=this.require;b.isUndefined=this.isUndefined;
     103b.checkPlugin=this.checkPlugin;b.getPlugin=this.getPlugin;b.addLocalPlugin=this.addLocalPlugin;b.getPluginsPath=this.getPluginsPath;b.getSymbolRecord=this.getSymbolRecord;b.verifySymbol=this.verifySymbol;b.runtimeError=this.runtimeError;b.nonNumericValueError=this.nonNumericValueError;b.variableDoesNotHoldAValueError=this.variableDoesNotHoldAValueError;b.reportError=this.reportError;b.register=this.register;b.symbols=f.getSymbols();b.encoding="ec";b.popups=[];b.stack=[];b.queue=[0];b.module=c;b.parent=
     104d;c&&(c.program=b);return b},tokeniseFile:function(a){var b=[],c=[],d=0;a.forEach(function(a,f){b.push({lino:f+1,line:a});for(var e=a.length,k="",h=!0,l=0;l<e;l++){var n=a[l];if(0==n.trim().length)h||(c.push({index:d,lino:f+1,token:k}),d++,k="",h=!0);else if(h=!1,"`"===n){for(m=l;++l<a.length&&"`"!==a[l];);k=a.substr(m,l-m+1)}else if("!"==n)break;else k+=n}0<k.length&&c.push({index:d,lino:f+1,token:k})});return{scriptLines:b,tokens:c}},tokeniseAndCompile:function(a,b,c,d,e){var f=null,g=Date.now();
     105a=this.tokeniseFile(a);try{f=this.compileScript(a,b,c,d);this.scriptIndex++;f.script||(f.script=this.scriptIndex);var k=Date.now();console.log(k-this.timestamp+" ms: Compiled "+(f.script+": "+a.scriptLines.length+" lines ("+a.tokens.length+" tokens) in ")+(k-g+" ms"))}catch(h){"stop"!==h.message&&(this.reportError(h,d,a),d&&d.onError&&d.run(d.onError))}f&&(f.onExit=e,f.running=!0,EasyCoder_Run.run(f,0))},tokenise:function(a){var b=a.split("\n");if(!this.tokenising){try{this.tokeniseAndCompile(b)}catch(c){this.reportError(c,
     106null,a)}this.tokenising=!0}},setPluginCount:function(a){EasyCoder.plugins=[];EasyCoder.pluginCount=a},checkPlugin:function(a){return EasyCoder.domain[a]},getPlugin:function(a,b,c){EasyCoder.domain[a]?c():(a=document.createElement("script"),a.type="text/javascript",a.src=b+"?ver="+EasyCoder.version,a.onload=function(){console.log(Date.now()-EasyCoder.timestamp+" ms: Plugin "+b+" loaded");c()},document.head.appendChild(a))},addGlobalPlugin:function(a,b){EasyCoder.plugins.push({name:a,handler:b});EasyCoder.plugins.length===
     107EasyCoder.pluginCount&&(EasyCoder.plugins.forEach(function(a){EasyCoder.domain[a.name]=a.handler}),EasyCoder.tokenise(EasyCoder.source))},addLocalPlugin:function(a,b,c){EasyCoder.domain[a]=b;c()},getPluginsPath:function(){return EasyCoder.pluginsPath},loadPluginJs:function(a){var b=this;console.log(Date.now()-this.timestamp+" ms: Load "+a+"/easycoder/plugins.js");var c=document.createElement("script");c.src=""+window.location.origin+a+"/easycoder/plugins.js?ver="+this.version;c.type="text/javascript";
     108c.onload=function(){EasyCoder_Plugins.getGlobalPlugins(b.timestamp,a,b.setPluginCount,b.getPlugin,b.addGlobalPlugin)};c.onerror=function(){a?b.loadPluginJs(a.slice(0,a.lastIndexOf("/"))):b.reportError({message:"Can't load plugins.js"},b.program,b.source)};document.head.appendChild(c);this.pluginsPath=a},start:function(a){this.source=a;this.scriptIndex=0;a=window.location.pathname;a=a.endsWith("/")?a.slice(0,-1):"";"undefined"===typeof EasyCoder_Plugins?this.loadPluginJs(a):(this.pluginsPath=a,EasyCoder_Plugins.getGlobalPlugins(this.timestamp,
     109a,this.setPluginCount,this.getPlugin,this.addGlobalPlugin))}},EasyCoder_Run={name:"EasyCoder_Run",run:function(a,b){var c=[],d=function(a){var b=9999;a.forEach(function(a){a=a.line;for(var c=0;c<a.length&&" "===a[c];)c++;0<c&&c<b&&(b=c)});return 0};if(c.length)c.push(b);else for(a.register(a),c.push(b);0<c.length;)for(a.pc=c.shift(),a.watchdog=0,b={};a.running;){if(1E6<a.watchdog){a.lino=a[a.pc].lino;a.reportError(Error("Program runaway intercepted.\nHave you forgotten to increment a loop counter?",
     110a),a);break}a.watchdog++;var e=a[a.pc].domain;a.debugStep&&console.log(a.script+": Line "+a[a.pc].lino+": PC: "+a.pc+" "+e+":"+a[a.pc].keyword);var f=a.domain[e];if(!f){a.runtimeError(a[a.pc].lino,"Unknown domain '"+e+"'");break}a.pc=f.run(a);if(!a.pc)break;if(a.stop){a.tracing=!1;break}if(a.tracing){e=a[a.pc];f=a.source.scriptLines;var g=d(f),k=document.getElementById("easycoder-tracer");if(!k){a.runtimeError(e.lino,"Element 'easycoder-tracer' was not found");return}k.style.display="block";k.style.visibility=
     111"visible";var h="";if(a.tracer){if(k=document.getElementById("easycoder-tracer-content")){a.tracer.variables.forEach(function(b,c,d){var e=a.getSymbolRecord(b);if(1<e.elements)for(h+=b+": "+e.index+"/"+e.elements+": ",b=0;b<e.elements;b++){var f=e.value[b];h=f?h+(f.content+" "):h+"undefined "}else h=(e=e.value[e.index])?h+(b+": "+e.content):h+(b+": undefined");switch(a.tracer.alignment){case "horizontal":c<d.length-1&&(h+=", ");break;case "vertical":h+="<br>"}});h+="<hr>";for(var l="",n=5;0<n;n--){if(e.lino){var q=
     112f[e.lino-n].line.substr(g);l+='<input type="text" name="'+n+'"value="'+(e.lino-n+1+": "+q.split("\\s").join(" ")+'"style="width:100%;border:none;enabled:false">')}l+="<br>"}k.innerHTML=h+" "+l;k.style.display="block";b.$jscomp$loop$prop$run$66=document.getElementById("easycoder-run-button");b.$jscomp$loop$prop$step$67=document.getElementById("easycoder-step-button");b.$jscomp$loop$prop$run$66.onclick=function(b){return function(){b.$jscomp$loop$prop$run$66.blur();a.tracing=!1;document.getElementById("easycoder-tracer-content").style.display=
     113"none";try{EasyCoder_Run.run(a,a.resume)}catch(p){var c="Error in run handler: "+p.message;console.log(c);alert(c)}}}(b);b.$jscomp$loop$prop$step$67.onclick=function(b){return function(){console.log("step");b.$jscomp$loop$prop$step$67.blur();a.tracing=!0;document.getElementById("easycoder-tracer-content").style.display="block";try{a.run(a.resume)}catch(p){var c="Error in step handler: "+p.message;console.log(c);alert(c)}}}(b)}a.resume=a.pc;a.pc=0}break}b={$jscomp$loop$prop$run$66:b.$jscomp$loop$prop$run$66,
     114$jscomp$loop$prop$step$67:b.$jscomp$loop$prop$step$67}}},exit:function(a){a.onExit&&(delete EasyCoder.scripts[a.script],a.parent.run(a.onExit),a.module.program=null,a.running=!1)}},EasyCoder_Value={name:"EasyCoder_Value",getItem:function(a){var b=a.getToken();if(!b)return null;if("true"===b)return a.next(),{type:"boolean",content:!0};if("false"===b)return a.next(),{type:"boolean",content:!1};if("`"===b.charAt(0))return a.next(),{type:"constant",numeric:!1,content:b.substring(1,b.length-1)};if(b.charAt(0).match(/[0-9-]/)){var c=
     115eval(b);if(Number.isInteger(c))return a.next(),{type:"constant",numeric:!0,content:c};throw Error("'"+b+"' is not an integer");}b=a.getIndex();c=$jscomp.makeIterator(Object.keys(a.domain));for(var d=c.next();!d.done;d=c.next())if(d=d.value,a.rewindTo(b),d=a.domain[d].value.compile(a))return d;return null},compile:function(a){var b=a.getToken(),c=EasyCoder_Value.getItem(a);if(!c)throw Error("Undefined value: '"+b+"'");if("cat"===a.getToken()){for(b={type:"cat",numeric:!1,parts:[c]};a.tokenIs("cat");)a.next(),
     116b.parts.push(a.value.getItem(a));return b}return c},doValue:function(a,b){if("undefined"===typeof b.type)return a.runtimeError(a[a.pc].lino,"Undefined value (variable not initialized?)"),null;switch(b.type){case "cat":return{type:"constant",numeric:!1,content:b.parts.reduce(function(b,c){return b+EasyCoder_Value.doValue(a,c).content},"")};case "boolean":case "constant":return b;case "symbol":var c=a.getSymbolRecord(b.name);if(c.isValueHolder){if(b=c.value[c.index]){c=b.content;if(null===c||"undefined"===
     117typeof c)b.content=b.numeric?0:"";return b}return null}return a.domain[c.domain].value.get(a,b)}return a.domain[b.domain].value.get(a,b)},constant:function(a,b){return{type:"constant",numeric:b,content:a}},evaluate:function(a,b){if(!b)return{type:"constant",numeric:!1,content:""};var c=EasyCoder_Value.doValue(a,b);if(c)return c;a.runtimeError(a[a.pc].lino,"Can't decode value: "+b)},getValue:function(a,b){return EasyCoder_Value.evaluate(a,b).content},encode:function(a,b){if(a)switch(b){case "ec":return a.replace(/'/g,
     118"~sq~").replace(/"/g,"~dq~").replace(/\n/g,"%0a").replace(/\r/g,"%0d");case "url":return encodeURIComponent(a.replace(/\s/g,"+"));case "sanitize":return a.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}return a},decode:function(a,b){if(a)switch(b){case "ec":return a.replace(/~dq~/g,'"').replace(/~sq~/g,"'").replace(/%0a/g,"\n").replace(/%0d/g,"\r");case "url":return decodeURIComponent(a).replace(/\+/g," ")}return a}};EasyCoder.version="2.5.2";EasyCoder.timestamp=Date.now();console.log("EasyCoder loaded; waiting for page");
     119function EasyCoder_Startup(){console.log(Date.now()-EasyCoder.timestamp+" ms: Page loaded; reset timer & start EasyCoder");EasyCoder.timestamp=Date.now();EasyCoder.scripts={};window.EasyCoder=EasyCoder;var a=document.getElementById("easycoder-script");if(a){a.style.display="none";try{EasyCoder.start(a.innerText)}catch(b){EasyCoder.reportError(b)}}}window.onload=EasyCoder_Startup;
  • easycoder/trunk/easycoder.js

    r2168730 r2208785  
    1 (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
    2 // EasyCoder
    3 
    4 const EasyCoder = require(`./easycoder/Main`);
    5 
    6 EasyCoder.version = `2.5.2`;
    7 EasyCoder.timestamp = Date.now();
    8 console.log(`EasyCoder loaded; waiting for page`);
    9 
    10 window.onload = function () {
    11     console.log(`${Date.now() - EasyCoder.timestamp} ms: Page loaded; reset timer & start EasyCoder`);
    12     EasyCoder.timestamp = Date.now();
    13     EasyCoder.scripts = {};
    14     window.EasyCoder = EasyCoder;
    15     const script = document.getElementById(`easycoder-script`);
    16     if (script) {
    17         script.style.display = `none`;
    18         try {
    19             EasyCoder.start(script.innerText);
    20         } catch (err) {
    21             EasyCoder.reportError(err);
    22         }
    23     }
    24 };
    25 },{"./easycoder/Main":6}],2:[function(require,module,exports){
     1// eslint-disable-next-line no-unused-vars
    262const EasyCoder_Compare = (program, value1, value2) => {
    273
     
    328    if (v1 && val1.numeric) {
    339        if (!val2.numeric) {
    34             v2 = typeof v2 === `undefined` ? 0 : parseInt(v2);
     10            v2 = (typeof v2 === `undefined`) ? 0 : parseInt(v2);
    3511        }
    3612    } else {
     
    5329    return 0;
    5430};
    55 
    56 module.exports = EasyCoder_Compare;
    57 },{}],3:[function(require,module,exports){
    58 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
    59 
    60 var _this = this;
    61 
     31// eslint-disable-next-line no-unused-vars
    6232const EasyCoder_Compiler = {
    6333
    64     getTokens: () => {
    65         return _this.tokens;
    66     },
    67 
    68     addWarning: message => {
    69         _this.warnings.push(message);
    70     },
    71 
    72     warning: message => {
    73         EasyCoder_Compiler.addWarning(message);
    74     },
    75 
    76     unrecognisedSymbol: item => {
    77         EasyCoder_Compiler.addWarning(`Unrecognised symbol '${item}'`);
    78     },
    79 
    80     getWarnings: () => {
    81         return _this.warnings;
    82     },
    83 
    84     getIndex: () => {
    85         return _this.index;
    86     },
    87 
    88     next: (step = 1) => {
    89         _this.index = _this.index + step;
    90     },
    91 
    92     peek: () => {
    93         return _this.tokens[_this.index + 1].token;
    94     },
    95 
    96     more: () => {
    97         return _this.index < _this.tokens.length;
    98     },
    99 
    100     getToken: () => {
    101         if (_this.index >= _this.tokens.length) {
     34    name: `EasyCoder_Compiler`,
     35
     36    getTokens: function() {
     37        return this.tokens;
     38    },
     39
     40    addWarning: function(message) {
     41        this.warnings.push(message);
     42    },
     43
     44    warning: function(message) {
     45        this.addWarning(message);
     46    },
     47
     48    unrecognisedSymbol: function(item) {
     49        this.addWarning(`Unrecognised symbol '${item}'`);
     50    },
     51
     52    getWarnings: function() {
     53        return this.warnings;
     54    },
     55
     56    getIndex: function() {
     57        return this.index;
     58    },
     59
     60    next: function(step = 1) {
     61        this.index = this.index + step;
     62    },
     63
     64    peek: function() {
     65        return this.tokens[this.index + 1].token;
     66    },
     67
     68    more: function() {
     69        return this.index < this.tokens.length;
     70    },
     71
     72    getToken: function() {
     73        if (this.index >= this.tokens.length) {
    10274            return null;
    10375        }
    104         const item = _this.tokens[_this.index];
    105         return item ? _this.tokens[_this.index].token : null;
    106     },
    107 
    108     nextToken: () => {
    109         EasyCoder_Compiler.next();
    110         return EasyCoder_Compiler.getToken();
    111     },
    112 
    113     tokenIs: token => {
    114         if (_this.index >= _this.tokens.length) {
     76        const item = this.tokens[this.index];
     77        return item ? this.tokens[this.index].token : null;
     78    },
     79
     80    nextToken: function() {
     81        this.next();
     82        return this.getToken();
     83    },
     84
     85    tokenIs: function(token) {
     86        if (this.index >= this.tokens.length) {
    11587            return false;
    11688        }
    117         return token === _this.tokens[_this.index].token;
    118     },
    119 
    120     nextTokenIs: token => {
    121         EasyCoder_Compiler.next();
    122         return EasyCoder_Compiler.tokenIs(token);
    123     },
    124 
    125     skip: token => {
    126         if (_this.index >= _this.tokens.length) {
     89        return token === this.tokens[this.index].token;
     90    },
     91
     92    nextTokenIs: function(token) {
     93        this.next();
     94        return this.tokenIs(token);
     95    },
     96
     97    skip: function(token) {
     98        if (this.index >= this.tokens.length) {
    12799            return null;
    128100        }
    129         EasyCoder_Compiler.next();
    130         if (EasyCoder_Compiler.tokenIs(token)) {
    131             EasyCoder_Compiler.next();
    132         }
    133     },
    134 
    135     prev: () => {
    136         _this.index--;
    137     },
    138 
    139     getLino: () => {
    140         if (_this.index >= _this.tokens.length) {
     101        this.next();
     102        if (this.tokenIs(token)) {
     103            this.next();
     104        }
     105    },
     106
     107    prev: function() {
     108        this.index--;
     109    },
     110
     111    getLino: function() {
     112        if (this.index >= this.tokens.length) {
    141113            return 0;
    142114        }
    143         return _this.tokens[_this.index].lino;
    144     },
    145 
    146     getTarget: (index = _this.index) => {
    147         return _this.tokens[index].token;
    148     },
    149 
    150     getTargetPc: (index = _this.index) => {
    151         return _this.symbols[EasyCoder_Compiler.getTarget(index)].pc;
    152     },
    153 
    154     getCommandAt: pc => {
    155         return _this.program[pc];
    156     },
    157 
    158     isSymbol: (required = false) => {
    159         const isSymbol = EasyCoder_Compiler.getTarget() in _this.symbols;
     115        return this.tokens[this.index].lino;
     116    },
     117
     118    getTarget: function(index = this.index) {
     119        return this.tokens[index].token;
     120    },
     121
     122    getTargetPc: function(index = this.index) {
     123        return this.symbols[this.getTarget(index)].pc;
     124    },
     125
     126    getCommandAt: function(pc) {
     127        return this.program[pc];
     128    },
     129
     130    isSymbol: function(required = false) {
     131        const isSymbol = this.getTarget() in this.symbols;
    160132        if (isSymbol) return true;
    161133        if (required) {
    162             throw new Error(`Unknown symbol: '${EasyCoder_Compiler.getTarget()}'`);
     134            throw new Error(`Unknown symbol: '${this.getTarget()}'`);
    163135        }
    164136        return false;
    165137    },
    166138
    167     nextIsSymbol: (required = false) => {
    168         EasyCoder_Compiler.next();
    169         return EasyCoder_Compiler.isSymbol(required);
    170     },
    171 
    172     getSymbol: () => {
    173         return _this.symbols[EasyCoder_Compiler.getToken()];
    174     },
    175 
    176     getSymbolPc: () => {
    177         return EasyCoder_Compiler.getSymbol().pc;
    178     },
    179 
    180     getSymbolRecord: () => {
    181         const record = _this.program[EasyCoder_Compiler.getSymbolPc()];
     139    nextIsSymbol: function(required = false) {
     140        this.next();
     141        return this.isSymbol(required);
     142    },
     143
     144    getSymbol: function(required = false) {
     145        if (this.isSymbol(required)) {
     146            return this.symbols[this.getToken()];
     147        }
     148    },
     149
     150    getSymbolPc: function(required = false) {
     151        return this.getSymbol(required).pc;
     152    },
     153
     154    getSymbolRecord: function() {
     155        const record = this.program[this.getSymbolPc(true)];
    182156        record.used = true;
    183157        return record;
    184158    },
    185159
    186     getSymbols: () => {
    187         return _this.symbols;
    188     },
    189 
    190     getProgram: () => {
    191         return _this.program;
    192     },
    193 
    194     getPc: () => {
    195         return _this.program.length;
    196     },
    197 
    198     getValue: () => {
    199         return EasyCoder_Compiler.value.compile(EasyCoder_Compiler);
    200     },
    201 
    202     getNextValue: () => {
    203         EasyCoder_Compiler.next();
    204         return EasyCoder_Compiler.getValue();
    205     },
    206 
    207     getCondition: () => {
    208         return EasyCoder_Compiler.condition.compile(EasyCoder_Compiler);
    209     },
    210 
    211     constant: (content, numeric = false) => {
    212         return EasyCoder_Compiler.value.constant(content, numeric);
    213     },
    214 
    215     addCommand: item => {
    216         const pc = _this.program.length;
    217         _this.program.push(_extends({
    218             pc
    219         }, item));
    220     },
    221 
    222     addSymbol: (name, pc) => {
    223         _this.symbols[name] = {
     160    getSymbols: function() {
     161        return this.symbols;
     162    },
     163
     164    getProgram: function() {
     165        return this.program;
     166    },
     167
     168    getPc: function() {
     169        return this.program.length;
     170    },
     171
     172    getValue: function() {
     173        return this.value.compile(this);
     174    },
     175
     176    getNextValue: function() {
     177        this.next();
     178        return this.getValue();
     179    },
     180
     181    getCondition: function() {
     182        return this.condition.compile(this);
     183    },
     184
     185    constant: function(content, numeric = false) {
     186        return this.value.constant(content, numeric);
     187    },
     188
     189    addCommand: function(item) {
     190        const pc = this.program.length;
     191        this.program.push({
     192            pc,
     193            ...item
     194        });
     195    },
     196
     197    addSymbol: function(name, pc) {
     198        this.symbols[name] = {
    224199            pc
    225200        };
    226201    },
    227202
    228     mark: () => {
    229         _this.savedMark = _this.index;
    230     },
    231 
    232     rewind: () => {
    233         _this.index = _this.savedMark;
    234     },
    235 
    236     rewindTo: index => {
    237         _this.index = index;
    238     },
    239 
    240     completeHandler: () => {
    241         const lino = EasyCoder_Compiler.getLino();
     203    mark: function() {
     204        this.savedMark = this.index;
     205    },
     206
     207    rewind: function() {
     208        this.index = this.savedMark;
     209    },
     210
     211    rewindTo: function(index) {
     212        this.index = index;
     213    },
     214
     215    completeHandler: function() {
     216        const lino = this.getLino();
    242217        // Add a 'goto' to skip the action
    243         const goto = EasyCoder_Compiler.getPc();
    244         EasyCoder_Compiler.addCommand({
     218        const goto = this.getPc();
     219        this.addCommand({
    245220            domain: `core`,
    246221            keyword: `goto`,
     
    249224        });
    250225        // Add the action
    251         EasyCoder_Compiler.compileOne();
     226        this.compileOne();
    252227        // Add a 'stop'
    253         EasyCoder_Compiler.addCommand({
     228        this.addCommand({
    254229            domain: `core`,
    255230            keyword: `stop`,
     
    258233        });
    259234        // Fixup the 'goto'
    260         EasyCoder_Compiler.getCommandAt(goto).goto = EasyCoder_Compiler.getPc();
     235        this.getCommandAt(goto).goto = this.getPc();
    261236        return true;
    262237    },
    263238
    264     compileVariable: (domain, keyword, isValueHolder = false, extra = null) => {
    265         EasyCoder_Compiler.next();
    266         const lino = EasyCoder_Compiler.getLino();
    267         const item = EasyCoder_Compiler.getTokens()[EasyCoder_Compiler.getIndex()];
    268         if (_this.symbols[item.token]) {
     239    compileVariable: function(domain, keyword, isValueHolder = false, extra = null) {
     240        this.next();
     241        const lino = this.getLino();
     242        const item = this.getTokens()[this.getIndex()];
     243        if (this.symbols[item.token]) {
    269244            throw new Error(`Duplicate variable name '${item.token}'`);
    270245        }
    271         const pc = EasyCoder_Compiler.getPc();
    272         EasyCoder_Compiler.next();
    273         EasyCoder_Compiler.addSymbol(item.token, pc);
     246        const pc = this.getPc();
     247        this.next();
     248        this.addSymbol(item.token, pc);
    274249        const command = {
    275250            domain,
     
    289264            command.element = [];
    290265        }
    291         EasyCoder_Compiler.addCommand(command);
     266        this.addCommand(command);
    292267        return command;
    293268    },
    294269
    295     compileToken: () => {
     270    compileToken: function() {
    296271        // Try each domain in turn until one can handle the command
    297         const token = EasyCoder_Compiler.getToken();
     272        const token = this.getToken();
    298273        if (!token) {
    299274            return;
    300275        }
    301276        // console.log(`Compile ${token}`);
    302         EasyCoder_Compiler.mark();
    303         for (const domainName of Object.keys(EasyCoder_Compiler.domain)) {
     277        this.mark();
     278        for (const domainName of Object.keys(this.domain)) {
    304279            //      console.log(`Try domain ${domainName} for token ${token}`);
    305             const domain = EasyCoder_Compiler.domain[domainName];
     280            const domain = this.domain[domainName];
    306281            if (domain) {
    307282                const handler = domain.getHandler(token);
    308283                if (handler) {
    309                     if (handler.compile(EasyCoder_Compiler)) {
     284                    if (handler.compile(this)) {
    310285                        return;
    311286                    }
    312287                }
    313288            }
    314             EasyCoder_Compiler.rewind();
     289            this.rewind();
    315290        }
    316291        console.log(`No handler found`);
     
    318293    },
    319294
    320     compileOne: () => {
    321         const keyword = EasyCoder_Compiler.getToken();
     295    compileOne: function() {
     296        const keyword = this.getToken();
    322297        if (!keyword) {
    323298            return;
    324299        }
    325300        // console.log(`Compile keyword '${keyword}'`);
    326         _this.warnings = [];
    327         const pc = _this.program.length;
     301        this.warnings = [];
     302        const pc = this.program.length;
    328303        // First check for a label
    329304        if (keyword.endsWith(`:`)) {
    330305            const name = keyword.substring(0, keyword.length - 1);
    331             if (_this.symbols[name]) {
     306            if (this.symbols[name]) {
    332307                throw new Error(`Duplicate symbol: '${name}'`);
    333308            }
    334             _this.symbols[name] = {
     309            this.symbols[name] = {
    335310                pc
    336311            };
    337             _this.index++;
     312            this.index++;
    338313        } else {
    339             EasyCoder_Compiler.compileToken();
    340         }
    341     },
    342 
    343     compileFromHere: stopOn => {
    344         while (_this.index < _this.tokens.length) {
    345             const token = _this.tokens[_this.index];
     314            this.compileToken();
     315        }
     316    },
     317
     318    compileFromHere: function(stopOn) {
     319        while (this.index < this.tokens.length) {
     320            const token = this.tokens[this.index];
    346321            const keyword = token.token;
    347322            if (keyword === `else`) {
    348                 return _this.program;
    349             }
    350             EasyCoder_Compiler.compileOne();
     323                return this.program;
     324            }
     325            this.compileOne();
    351326            if (stopOn.indexOf(keyword) > -1) {
    352327                break;
     
    355330    },
    356331
    357     compile: tokens => {
    358         _this.tokens = tokens;
    359         _this.index = 0;
    360         _this.program = [];
    361         _this.symbols = {};
    362         _this.warnings = [];
    363         EasyCoder_Compiler.compileFromHere([]);
    364         EasyCoder_Compiler.addCommand({
     332    compile: function(tokens) {
     333        this.tokens = tokens;
     334        this.index = 0;
     335        this.program = [];
     336        this.program.symbols = {};
     337        this.symbols = this.program.symbols;
     338        this.warnings = [];
     339        this.compileFromHere([]);
     340        this.addCommand({
    365341            domain: `core`,
    366342            keyword: `exit`,
    367             lino: EasyCoder_Compiler.getLino(),
     343            lino: this.getLino(),
    368344            next: 0
    369345        });
    370346        //    console.log('Symbols: ' + JSON.stringify(this.symbols, null, 2));
    371         for (const symbol in _this.symbols) {
    372             const record = _this.program[_this.symbols[symbol].pc];
    373             if (record.isSymbol && !record.used) {
     347        for (const symbol in this.symbols) {
     348            const record = this.program[this.symbols[symbol].pc];
     349            if (record.isSymbol && !record.used && !record.exporter) {
    374350                console.log(`Symbol '${record.name}' has not been used.`);
    375351            }
    376352        }
    377         return _this.program;
     353        return this.program;
    378354    }
    379355};
    380 
    381 module.exports = EasyCoder_Compiler;
    382 },{}],4:[function(require,module,exports){
    383 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
    384 
     356// eslint-disable-next-line no-unused-vars
    385357const EasyCoder_Condition = {
    386358
    387     compile: compiler => {
     359    name: `EasyCoder_Condition`,
     360
     361    compile: (compiler) => {
    388362        // See if any of the domains can handle it
    389363        compiler.mark();
     
    393367            const code = domain.condition.compile(compiler);
    394368            if (code) {
    395                 return _extends({
    396                     domain: name
    397                 }, code);
     369                return {
     370                    domain: name,
     371                    ...code
     372                };
    398373            }
    399374            compiler.rewind();
     
    408383    }
    409384};
    410 
    411 module.exports = EasyCoder_Condition;
    412 },{}],5:[function(require,module,exports){
    413 var _this = this;
    414 
    415385const EasyCoder_Core = {
     386
     387    name: `EasyCoder_Core`,
    416388
    417389    Add: {
     
    457429                        return true;
    458430                    }
    459                     compiler.warning(`core ${_this.name}: Expected value holder`);
     431                    compiler.warning(`core 'add': Expected value holder`);
    460432                } else {
    461433                    // Here we have 2 values so 'giving' must come next
     
    475447                        return true;
    476448                    }
    477                     compiler.warning(`core ${_this.name}: Expected "giving"`);
     449                    compiler.warning(`core 'add'': Expected "giving"`);
    478450                }
    479451            }
     
    491463                const value = target.value[target.index];
    492464                if (value2) {
    493                     const result = program.getValue(value2) + program.getValue(value1);
     465                    const result = program.getValue(value2) +
     466                        program.getValue(value1);
    494467                    target.value[target.index] = {
    495468                        type: `constant`,
     
    761734            const item = command.item;
    762735            switch (item) {
    763                 case `symbols`:
    764                     console.log(`Symbols: ${JSON.stringify(program.symbols, null, 2)}`);
    765                     break;
    766                 case `symbol`:
    767                     const record = program.getSymbolRecord(command.name);
    768                     const exporter = record.exporter;
    769                     delete record.exporter;
    770                     console.log(`Symbol: ${JSON.stringify(record, null, 2)}`);
    771                     record.exporter = exporter;
    772                     break;
    773                 case `step`:
    774                     program.debugStep = true;
    775                     break;
    776                 case `program`:
    777                     console.log(`Debug program: ${JSON.stringify(program, null, 2)}`);
    778                     break;
    779                 default:
    780                     if (item.content >= 0) {
    781                         console.log(`Debug item ${item.content}: ${JSON.stringify(program[item.content], null, 2)}`);
    782                     }
    783                     break;
     736            case `symbols`:
     737                console.log(`Symbols: ${JSON.stringify(program.symbols, null, 2)}`);
     738                break;
     739            case `symbol`:
     740                const record = program.getSymbolRecord(command.name);
     741                const exporter = record.exporter.script;
     742                delete record.exporter;
     743                console.log(`Symbol: ${JSON.stringify(record, null, 2)}`);
     744                record.exporter.script = exporter;
     745                break;
     746            case `step`:
     747                program.debugStep = true;
     748                break;
     749            case `program`:
     750                console.log(`Debug program: ${JSON.stringify(program, null, 2)}`);
     751                break;
     752            default:
     753                if (item.content >= 0) {
     754                    console.log(`Debug item ${item.content}: ${JSON.stringify(program[item.content], null, 2)}`);
     755                }
     756                break;
    784757            }
    785758            return command.pc + 1;
     
    858831                    return true;
    859832                }
    860                 compiler.warning(`core ${_this.name}: Expected value holder`);
     833                compiler.warning(`core 'divide'': Expected value holder`);
    861834            } else {
    862835                // Here we should already have the target.
    863836                if (typeof target === `undefined`) {
    864                     compiler.warning(`core ${_this.name}: No target variable given`);
     837                    compiler.warning(`core 'divide': No target variable given`);
    865838                }
    866839                compiler.addCommand({
     
    987960
    988961        run: program => {
     962            program.parent.run(program.parent.nextPc);
     963            program.parent.nextPc = 0;
    989964            program.exit();
    990965            return 0;
     
    11531128                    domain: `core`,
    11541129                    keyword: `goto`,
     1130                    lino,
    11551131                    goto: 0
    11561132                });
     
    11851161        compile: compiler => {
    11861162            const imports = compiler.imports;
     1163            let caller = EasyCoder.scripts[imports.caller];
    11871164            const program = compiler.getProgram();
    11881165            if (imports.length) {
    1189                 for (const symbolRecord of imports) {
     1166                for (const name of imports) {
     1167                    let symbolRecord = caller.getSymbolRecord(name);
    11901168                    const thisType = compiler.nextToken();
    11911169                    const exportedType = symbolRecord.keyword;
     
    11941172                        const newRecord = program[compiler.getSymbols()[command.name].pc];
    11951173                        newRecord.element = symbolRecord.element;
    1196                         newRecord.exporter = symbolRecord.exporter;
     1174                        newRecord.exporter = symbolRecord.exporter ? symbolRecord.exporter : caller.script;
    11971175                        newRecord.exportedName = symbolRecord.name;
    11981176                        newRecord.extra = symbolRecord.extra;
    11991177                        newRecord.isValueHolder = symbolRecord.isValueHolder;
     1178                        if (symbolRecord.program) {
     1179                            newRecord.program = symbolRecord.program;
     1180                        }
    12001181                        newRecord.imported = true;
    12011182                        if (!compiler.tokenIs(`and`)) {
     
    12491230            const index = program.getValue(command.value);
    12501231            if (index >= symbol.elements) {
    1251                 program.runtimeError(command.lino, `Array index ${index} is out of range for '${symbol.name}'`);
     1232                program.runtimeError(command.lino,
     1233                    `Array index ${index} is out of range for '${symbol.name}'`);
    12521234            }
    12531235            symbol.index = index;
    12541236            if (symbol.imported) {
    1255                 const exporterRecord = symbol.exporter.getSymbolRecord(symbol.exportedName);
     1237                const exporterRecord = EasyCoder.symbols[symbol.exporter].getSymbolRecord(symbol.exportedName);
    12561238                exporterRecord.index = index;
    12571239            }
     
    12661248            const type = compiler.nextToken();
    12671249            switch (type) {
    1268                 case `plugin`:
    1269                     const name = compiler.getNextValue();
    1270                     compiler.addCommand({
    1271                         domain: `core`,
    1272                         keyword: `load`,
    1273                         lino,
    1274                         name
    1275                     });
    1276                     return true;
     1250            case `plugin`:
     1251                const name = compiler.getNextValue();
     1252                compiler.addCommand({
     1253                    domain: `core`,
     1254                    keyword: `load`,
     1255                    lino,
     1256                    name
     1257                });
     1258                return true;
    12771259            }
    12781260            return false;
     
    12831265            const name = program.getValue(command.name);
    12841266            switch (command.keyword) {
    1285                 case `load`:
    1286                     if (program.checkPlugin(name)) {
    1287                         return command.pc + 1;
    1288                     }
    1289                     EasyCoder_Plugins.getLocalPlugin(program.getPluginsPath, name, program.getPlugin, program.addLocalPlugin, function () {
     1267            case `load`:
     1268                if (program.checkPlugin(name)) {
     1269                    return command.pc + 1;
     1270                }
     1271                EasyCoder_Plugins.getLocalPlugin(
     1272                    program.getPluginsPath,
     1273                    name,
     1274                    program.getPlugin,
     1275                    program.addLocalPlugin,
     1276                    function () {
    12901277                        program.run(command.pc + 1);
    12911278                    });
    1292                     return 0;
     1279                return 0;
    12931280            }
    12941281        }
     
    13041291        run: program => {
    13051292            const command = program[program.pc];
    1306             command.program = null;
    13071293            return command.pc + 1;
    13081294        }
     
    13711357                const value = target.value[target.index];
    13721358                if (value1) {
    1373                     const result = program.getValue(value1) * program.getValue(value2);
     1359                    const result = program.getValue(value1) *
     1360                        program.getValue(value2);
    13741361                    target.value[target.index] = {
    13751362                        type: `constant`,
     
    14361423            const action = compiler.nextToken();
    14371424            switch (action) {
    1438                 case `close`:
    1439                 case `message`:
    1440                 case `error`:
    1441                     compiler.next();
    1442                     compiler.addCommand({
    1443                         domain: `core`,
    1444                         keyword: `on`,
    1445                         lino,
    1446                         action
    1447                     });
    1448                     return compiler.completeHandler();
     1425            case `close`:
     1426            case `message`:
     1427            case `error`:
     1428                compiler.next();
     1429                compiler.addCommand({
     1430                    domain: `core`,
     1431                    keyword: `on`,
     1432                    lino,
     1433                    action
     1434                });
     1435                return compiler.completeHandler();
    14491436            }
    14501437            if (compiler.isSymbol()) {
     
    14681455            const cb = command.pc + 2;
    14691456            switch (command.action) {
    1470                 case `close`:
    1471                     program.onClose = cb;
    1472                     break;
    1473                 case `message`:
    1474                     program.onMessage = cb;
    1475                     break;
    1476                 case `error`:
    1477                     program.onError = cb;
    1478                     break;
    1479                 default:
    1480                     const callbacklRecord = program.getSymbolRecord(command.action);
    1481                     if (callbacklRecord) {
    1482                         callbacklRecord.cb = cb;
    1483                     } else {
    1484                         program.runtimeError(command.lino, `Unknown action '${command.action}'`);
    1485                         return 0;
    1486                     }
     1457            case `close`:
     1458                program.onClose = cb;
     1459                break;
     1460            case `message`:
     1461                program.onMessage = cb;
     1462                break;
     1463            case `error`:
     1464                program.onError = cb;
     1465                break;
     1466            default:
     1467                const callbacklRecord = program.getSymbolRecord(command.action);
     1468                if (callbacklRecord) {
     1469                    callbacklRecord.cb = cb;
     1470                } else {
     1471                    program.runtimeError(command.lino, `Unknown action '${command.action}'`);
     1472                    return 0;
     1473                }
    14871474            }
    14881475            return command.pc + 1;
     
    15531540            };
    15541541            if (target.imported) {
    1555                 const exporterRecord = target.exporter.getSymbolRecord(target.exportedName);
     1542                const exporterRecord = EasyCoder.scripts[target.exporter].getSymbolRecord(target.exportedName);
    15561543                exporterRecord.value[exporterRecord.index] = value;
    15571544            }
     
    16311618        run: program => {
    16321619            const command = program[program.pc];
    1633             program.require(command.type, program.getValue(command.url), function () {
    1634                 program.run(command.pc + 1);
    1635             });
     1620            program.require(command.type, program.getValue(command.url),
     1621                function () {
     1622                    program.run(command.pc + 1);
     1623                });
    16361624            return 0;
    16371625        }
     
    16631651            const lino = compiler.getLino();
    16641652            const script = compiler.getNextValue();
     1653            let program = compiler.getProgram();
    16651654            const imports = [];
    16661655            if (compiler.tokenIs(`with`)) {
     
    16681657                    if (compiler.nextIsSymbol(true)) {
    16691658                        const symbolRecord = compiler.getSymbolRecord();
    1670                         symbolRecord.exporter = compiler.getProgram();
    1671                         imports.push(symbolRecord);
     1659                        // symbolRecord.exporter = program.script;
     1660                        imports.push(symbolRecord.name);
    16721661                        compiler.next();
    16731662                        if (!compiler.tokenIs(`and`)) {
     
    16811670                if (compiler.nextIsSymbol(true)) {
    16821671                    const moduleRecord = compiler.getSymbolRecord();
     1672                    moduleRecord.program = program;
    16831673                    compiler.next();
    16841674                    if (moduleRecord.keyword !== `module`) {
     
    17671757
    17681758        compile: compiler => {
    1769             // const lino = compiler.getLino();
    1770             // const name = compiler.nextToken();
    17711759            const program = compiler.getProgram();
    17721760            program.script = compiler.nextToken();
     1761            if (EasyCoder.scripts[program.script]) {
     1762                throw new Error(`Script '${program.script}' is already running.`);
     1763            }
    17731764            EasyCoder.scripts[program.script] = program;
    17741765            compiler.next();
    1775             // compiler.addCommand({
    1776             //  domain: `core`,
    1777             //  keyword: `script`,
    1778             //  lino,
    1779             //  name
    1780             // });
    17811766            return true;
    17821767        },
    17831768
    17841769        run: program => {
    1785             const command = program[program.pc];
    1786             // program.script = command.name;
    1787             // EasyCoder.scripts[command.name] = program;
    1788             // console.log(`${Date.now() - EasyCoder.timestamp} ms: Script: ${command.name}`);
    1789             return command.pc + 1;
     1770            return program[program.pc].pc + 1;
    17901771        }
    17911772    },
     
    18871868            }
    18881869            switch (compiler.getToken()) {
    1889                 case `ready`:
    1890                     compiler.next();
    1891                     compiler.addCommand({
    1892                         domain: `core`,
    1893                         keyword: `set`,
    1894                         lino,
    1895                         request: `setReady`
    1896                     });
    1897                     return true;
    1898                 case `element`:
    1899                     const index = compiler.getNextValue();
    1900                     if (compiler.tokenIs(`of`)) {
    1901                         if (compiler.nextIsSymbol()) {
    1902                             const targetRecord = compiler.getSymbolRecord();
    1903                             if (targetRecord.keyword === `variable`) {
    1904                                 if (compiler.nextTokenIs(`to`)) {
    1905                                     const value = compiler.getNextValue();
    1906                                     compiler.addCommand({
    1907                                         domain: `core`,
    1908                                         keyword: `set`,
    1909                                         lino,
    1910                                         request: `setElement`,
    1911                                         target: targetRecord.name,
    1912                                         index,
    1913                                         value
    1914                                     });
    1915                                     return true;
    1916                                 }
    1917                             }
    1918                         }
    1919                     }
    1920                     break;
    1921                 case `property`:
    1922                     name = compiler.getNextValue();
    1923                     if (compiler.tokenIs(`of`)) {
    1924                         if (compiler.nextIsSymbol()) {
    1925                             const targetRecord = compiler.getSymbolRecord();
    1926                             if (targetRecord.keyword === `variable`) {
    1927                                 if (compiler.nextTokenIs(`to`)) {
    1928                                     const value = compiler.getNextValue();
    1929                                     compiler.addCommand({
    1930                                         domain: `core`,
    1931                                         keyword: `set`,
    1932                                         lino,
    1933                                         request: `setProperty`,
    1934                                         target: targetRecord.name,
    1935                                         name,
    1936                                         value
    1937                                     });
    1938                                     return true;
    1939                                 }
    1940                             }
    1941                         }
    1942                     }
    1943                     break;
    1944                 case `arg`:
    1945                     name = compiler.getNextValue();
    1946                     if (compiler.tokenIs(`of`)) {
    1947                         if (compiler.nextIsSymbol()) {
    1948                             const targetRecord = compiler.getSymbolRecord();
     1870            case `ready`:
     1871                compiler.next();
     1872                compiler.addCommand({
     1873                    domain: `core`,
     1874                    keyword: `set`,
     1875                    lino,
     1876                    request: `setReady`
     1877                });
     1878                return true;
     1879            case `element`:
     1880                const index = compiler.getNextValue();
     1881                if (compiler.tokenIs(`of`)) {
     1882                    if (compiler.nextIsSymbol()) {
     1883                        const targetRecord = compiler.getSymbolRecord();
     1884                        if (targetRecord.keyword === `variable`) {
    19491885                            if (compiler.nextTokenIs(`to`)) {
    19501886                                const value = compiler.getNextValue();
     
    19531889                                    keyword: `set`,
    19541890                                    lino,
    1955                                     request: `setArg`,
     1891                                    request: `setElement`,
     1892                                    target: targetRecord.name,
     1893                                    index,
     1894                                    value
     1895                                });
     1896                                return true;
     1897                            }
     1898                        }
     1899                    }
     1900                }
     1901                break;
     1902            case `property`:
     1903                name = compiler.getNextValue();
     1904                if (compiler.tokenIs(`of`)) {
     1905                    if (compiler.nextIsSymbol()) {
     1906                        const targetRecord = compiler.getSymbolRecord();
     1907                        if (targetRecord.keyword === `variable`) {
     1908                            if (compiler.nextTokenIs(`to`)) {
     1909                                const value = compiler.getNextValue();
     1910                                compiler.addCommand({
     1911                                    domain: `core`,
     1912                                    keyword: `set`,
     1913                                    lino,
     1914                                    request: `setProperty`,
    19561915                                    target: targetRecord.name,
    19571916                                    name,
     
    19621921                        }
    19631922                    }
    1964             }
    1965             if (compiler.tokenIs(`the`)) {
    1966                 compiler.next();
    1967             }
    1968             switch (compiler.getToken()) {
    1969                 case `elements`:
    1970                     compiler.next();
    1971                     if (compiler.tokenIs(`of`)) {
    1972                         compiler.next();
    1973                         if (!compiler.isSymbol()) {
    1974                             throw new Error(`Unknown variable '${compiler.getToken()}'`);
    1975                         }
    1976                         const symbol = compiler.getToken();
    1977                         compiler.next();
    1978                         if (compiler.tokenIs(`to`)) {
    1979                             compiler.next();
    1980                             // get the value
    1981                             const value = compiler.getValue();
     1923                }
     1924                break;
     1925            case `arg`:
     1926                name = compiler.getNextValue();
     1927                if (compiler.tokenIs(`of`)) {
     1928                    if (compiler.nextIsSymbol()) {
     1929                        const targetRecord = compiler.getSymbolRecord();
     1930                        if (compiler.nextTokenIs(`to`)) {
     1931                            const value = compiler.getNextValue();
    19821932                            compiler.addCommand({
    19831933                                domain: `core`,
    19841934                                keyword: `set`,
    19851935                                lino,
    1986                                 request: `setElements`,
    1987                                 symbol,
     1936                                request: `setArg`,
     1937                                target: targetRecord.name,
     1938                                name,
    19881939                                value
    19891940                            });
     
    19911942                        }
    19921943                    }
    1993                     break;
    1994                 case `encoding`:
    1995                     if (compiler.nextTokenIs(`to`)) {
    1996                         const encoding = compiler.getNextValue();
     1944                }
     1945            }
     1946            if (compiler.tokenIs(`the`)) {
     1947                compiler.next();
     1948            }
     1949            switch (compiler.getToken()) {
     1950            case `elements`:
     1951                compiler.next();
     1952                if (compiler.tokenIs(`of`)) {
     1953                    compiler.next();
     1954                    if (!compiler.isSymbol()) {
     1955                        throw new Error(`Unknown variable '${compiler.getToken()}'`);
     1956                    }
     1957                    const symbol = compiler.getToken();
     1958                    compiler.next();
     1959                    if (compiler.tokenIs(`to`)) {
     1960                        compiler.next();
     1961                        // get the value
     1962                        const value = compiler.getValue();
    19971963                        compiler.addCommand({
    19981964                            domain: `core`,
    19991965                            keyword: `set`,
    2000                             request: `encoding`,
    20011966                            lino,
    2002                             encoding
     1967                            request: `setElements`,
     1968                            symbol,
     1969                            value
    20031970                        });
    20041971                        return true;
    20051972                    }
    2006                     compiler.addWarning(`Unknown encoding option`);
    2007                     break;
    2008                 case `payload`:
    2009                     if (compiler.nextTokenIs(`of`)) {
    2010                         if (compiler.nextIsSymbol()) {
    2011                             const callbackRecord = compiler.getSymbolRecord();
    2012                             if (callbackRecord.keyword === `callback`) {
    2013                                 if (compiler.nextTokenIs(`to`)) {
    2014                                     const payload = compiler.getNextValue();
    2015                                     compiler.addCommand({
    2016                                         domain: `core`,
    2017                                         keyword: `set`,
    2018                                         request: `setPayload`,
    2019                                         lino,
    2020                                         callback: callbackRecord.name,
    2021                                         payload
    2022                                     });
    2023                                     return true;
    2024                                 }
     1973                }
     1974                break;
     1975            case `encoding`:
     1976                if (compiler.nextTokenIs(`to`)) {
     1977                    const encoding = compiler.getNextValue();
     1978                    compiler.addCommand({
     1979                        domain: `core`,
     1980                        keyword: `set`,
     1981                        request: `encoding`,
     1982                        lino,
     1983                        encoding
     1984                    });
     1985                    return true;
     1986                }
     1987                compiler.addWarning(`Unknown encoding option`);
     1988                break;
     1989            case `payload`:
     1990                if (compiler.nextTokenIs(`of`)) {
     1991                    if (compiler.nextIsSymbol()) {
     1992                        const callbackRecord = compiler.getSymbolRecord();
     1993                        if (callbackRecord.keyword === `callback`) {
     1994                            if (compiler.nextTokenIs(`to`)) {
     1995                                const payload = compiler.getNextValue();
     1996                                compiler.addCommand({
     1997                                    domain: `core`,
     1998                                    keyword: `set`,
     1999                                    request: `setPayload`,
     2000                                    lino,
     2001                                    callback: callbackRecord.name,
     2002                                    payload
     2003                                });
     2004                                return true;
    20252005                            }
    20262006                        }
    20272007                    }
     2008                }
    20282009            }
    20292010            return false;
     
    20342015            const command = program[program.pc];
    20352016            switch (command.request) {
    2036                 case `setBoolean`:
    2037                     const target = program.getSymbolRecord(command.target);
    2038                     if (target.isValueHolder) {
    2039                         target.value[target.index] = {
    2040                             type: `boolean`,
    2041                             content: true
    2042                         };
    2043                         command.numeric = false;
     2017            case `setBoolean`:
     2018                const target = program.getSymbolRecord(command.target);
     2019                if (target.isValueHolder) {
     2020                    target.value[target.index] = {
     2021                        type: `boolean`,
     2022                        content: true
     2023                    };
     2024                    command.numeric = false;
     2025                } else {
     2026                    program.variableDoesNotHoldAValueError(command.lino, target.name);
     2027                }
     2028                break;
     2029            case `setReady`:
     2030                program.parent.run(program.parent.nextPc);
     2031                program.parent.nextPc = 0;
     2032                break;
     2033            case `setArray`:
     2034                targetRecord = program.getSymbolRecord(command.target);
     2035                targetRecord.elements = command.value.length;
     2036                targetRecord.value = command.value;
     2037                break;
     2038            case `encoding`:
     2039                program.encoding = program.getValue(command.encoding);
     2040                break;
     2041            case `setElements`:
     2042                const symbol = program.getSymbolRecord(command.symbol);
     2043                const oldCount = symbol.elements;
     2044                symbol.elements = program.getValue(command.value);
     2045                symbol.index = 0;
     2046                if (symbol.elements > oldCount) {
     2047                    for (var n = oldCount; n < symbol.elements; n++) {
     2048                        symbol.value.push({});
     2049                        symbol.element.push({});
     2050                    }
     2051                } else {
     2052                    symbol.value = symbol.value.slice(0, symbol.elements);
     2053                    symbol.element = symbol.element.slice(0, symbol.elements);
     2054                }
     2055                break;
     2056            case `setElement`:
     2057                targetRecord = program.getSymbolRecord(command.target);
     2058                const index = program.getValue(command.index);
     2059                const elements = JSON.parse(program.getValue(targetRecord.value[targetRecord.index]));
     2060                const value = program.getValue(command.value);
     2061                elements[index] = JSON.parse(value);
     2062                targetRecord.value[targetRecord.index].content = JSON.stringify(elements);
     2063                break;
     2064            case `setProperty`:
     2065                targetRecord = program.getSymbolRecord(command.target);
     2066                let targetValue = program.getValue(targetRecord.value[targetRecord.index]);
     2067                if (!targetValue) {
     2068                    targetValue = `{}`;
     2069                }
     2070                let targetJSON = ``;
     2071                try {
     2072                    targetJSON = JSON.parse(targetValue);
     2073                } catch (err) {
     2074                    program.runtimeError(command.lino, `Can't parse ${targetRecord.name}`);
     2075                    return 0;
     2076                }
     2077                const itemName = program.getValue(command.name);
     2078                const itemValue = program.evaluate(command.value);
     2079                if (itemValue) {
     2080                    if (itemValue.content instanceof Array) {
     2081                        targetJSON[itemName] = itemValue.content;
     2082                    } else if (itemValue.type === `boolean`) {
     2083                        targetJSON[itemName] = itemValue.content;
     2084                    } else if (itemValue.numeric) {
     2085                        targetJSON[itemName] = itemValue.content;
     2086                    } else if (itemValue.content.substr(0, 2) === `{"`) {
     2087                        targetJSON[itemName] = JSON.parse(itemValue.content);
    20442088                    } else {
    2045                         program.variableDoesNotHoldAValueError(command.lino, target.name);
    2046                     }
    2047                     break;
    2048                 case `setReady`:
    2049                     program.parent.run(program.parent.nextPc);
    2050                     program.parent.nextPc = 0;
    2051                     break;
    2052                 case `setArray`:
    2053                     targetRecord = program.getSymbolRecord(command.target);
    2054                     targetRecord.elements = command.value.length;
    2055                     targetRecord.value = command.value;
    2056                     break;
    2057                 case `encoding`:
    2058                     program.encoding = program.getValue(command.encoding);
    2059                     break;
    2060                 case `setElements`:
    2061                     const symbol = program.getSymbolRecord(command.symbol);
    2062                     const oldCount = symbol.elements;
    2063                     symbol.elements = program.getValue(command.value);
    2064                     symbol.index = 0;
    2065                     if (symbol.elements > oldCount) {
    2066                         for (var n = oldCount; n < symbol.elements; n++) {
    2067                             symbol.value.push({});
    2068                             symbol.element.push({});
    2069                         }
    2070                     } else {
    2071                         symbol.value = symbol.value.slice(0, symbol.elements);
    2072                         symbol.element = symbol.element.slice(0, symbol.elements);
    2073                     }
    2074                     break;
    2075                 case `setElement`:
    2076                     targetRecord = program.getSymbolRecord(command.target);
    2077                     const index = program.getValue(command.index);
    2078                     const elements = JSON.parse(program.getValue(targetRecord.value[targetRecord.index]));
    2079                     const value = program.getValue(command.value);
    2080                     elements[index] = JSON.parse(value);
    2081                     targetRecord.value[targetRecord.index].content = JSON.stringify(elements);
    2082                     break;
    2083                 case `setProperty`:
    2084                     targetRecord = program.getSymbolRecord(command.target);
    2085                     let targetValue = program.getValue(targetRecord.value[targetRecord.index]);
    2086                     if (!targetValue) {
    2087                         targetValue = `{}`;
    2088                     }
    2089                     let targetJSON = ``;
    2090                     try {
    2091                         targetJSON = JSON.parse(targetValue);
    2092                     } catch (err) {
    2093                         program.runtimeError(command.lino, `Can't parse ${targetRecord.name}`);
    2094                         return 0;
    2095                     }
    2096                     const itemName = program.getValue(command.name);
    2097                     const itemValue = program.evaluate(command.value);
    2098                     if (itemValue) {
    2099                         if (itemValue.content instanceof Array) {
    2100                             targetJSON[itemName] = itemValue.content;
    2101                         } else if (itemValue.type === `boolean`) {
    2102                             targetJSON[itemName] = itemValue.content;
    2103                         } else if (itemValue.numeric) {
    2104                             targetJSON[itemName] = itemValue.content;
    2105                         } else if (itemValue.content.substr(0, 2) === `{"`) {
    2106                             targetJSON[itemName] = JSON.parse(itemValue.content);
    2107                         } else {
    2108                             targetJSON[itemName] = itemValue.content.split(`"`).join(`\\"`);
    2109                         }
    2110                         targetRecord.value[targetRecord.index] = {
    2111                             type: `constant`,
    2112                             numeric: false,
    2113                             content: JSON.stringify(targetJSON)
    2114                         };
    2115                     }
    2116                     break;
    2117                 case `setPayload`:
    2118                     program.getSymbolRecord(command.callback).payload = program.getValue(command.payload);
    2119                     break;
    2120                 case `setArg`:
    2121                     const name = program.getValue(command.name);
    2122                     targetRecord = program.getSymbolRecord(command.target);
    2123                     targetRecord[name] = program.getValue(command.value);
    2124                     break;
    2125                 default:
    2126                     break;
     2089                        targetJSON[itemName] = itemValue.content.split(`"`).join(`\\"`);
     2090                    }
     2091                    targetRecord.value[targetRecord.index] = {
     2092                        type: `constant`,
     2093                        numeric: false,
     2094                        content: JSON.stringify(targetJSON)
     2095                    };
     2096                }
     2097                break;
     2098            case `setPayload`:
     2099                program.getSymbolRecord(command.callback).payload = program.getValue(command.payload);
     2100                break;
     2101            case `setArg`:
     2102                const name = program.getValue(command.name);
     2103                targetRecord = program.getSymbolRecord(command.target);
     2104                targetRecord[name] = program.getValue(command.value);
     2105                break;
     2106            default:
     2107                break;
    21272108            }
    21282109            return command.pc + 1;
     
    21692150                program.runtimeError(command.lino, `Can't parse this array`);
    21702151            }
     2152            return command.pc + 1;
     2153        }
     2154    },
     2155
     2156    Split: {
     2157
     2158        compile: compiler => {
     2159            const lino = compiler.getLino();
     2160            item = compiler.getNextValue();
     2161            let on = `\n`;
     2162            if (compiler.tokenIs(`on`)) {
     2163                on = compiler.getNextValue();
     2164            }
     2165            if ([`giving`, `into`].includes(compiler.getToken())) {
     2166                if (compiler.nextIsSymbol()) {
     2167                    const targetRecord = compiler.getSymbolRecord();
     2168                    if (targetRecord.keyword === `variable`) {
     2169                        compiler.next();
     2170                        compiler.addCommand({
     2171                            domain: `core`,
     2172                            keyword: `split`,
     2173                            lino,
     2174                            item,
     2175                            on,
     2176                            target: targetRecord.name
     2177                        });
     2178                        return true;
     2179                    }
     2180                }
     2181            }
     2182            return false;
     2183        },
     2184
     2185        run: program => {
     2186            let command = program[program.pc];
     2187            let content = program.getValue(command.item);
     2188            let on = program.getValue(command.on);
     2189            content = content.split(on);
     2190            let elements = content.length;
     2191            targetRecord = program.getSymbolRecord(command.target);
     2192            targetRecord.elements = elements;
     2193            for (let n = 0; n < elements; n++) {
     2194                targetRecord.value[n] = {
     2195                    type: `constant`,
     2196                    numeric: false,
     2197                    content: content[n]
     2198                };
     2199            }
     2200            targetRecord.index = 0;
    21712201            return command.pc + 1;
    21722202        }
     
    22552285                        return true;
    22562286                    } else {
    2257                         compiler.warning(`core ${_this.name}: Expected value holder`);
     2287                        compiler.warning(`core 'take'': Expected value holder`);
    22582288                    }
    22592289                } else {
     
    22742304                        return true;
    22752305                    } else {
    2276                         compiler.warning(`core ${_this.name}: Expected "giving"`);
     2306                        compiler.warning(`core 'take'': Expected "giving"`);
    22772307                    }
    22782308                }
     
    22892319                const value = target.value[target.index];
    22902320                if (value2) {
    2291                     const result = program.getValue(value2) - program.getValue(value1);
     2321                    const result = program.getValue(value2) -
     2322                        program.getValue(value1);
    22922323                    target.value[target.index] = {
    22932324                        type: `constant`,
     
    23702401            let multiplier = 1000;
    23712402            switch (scale) {
    2372                 case `milli`:
    2373                 case `millis`:
    2374                     compiler.next();
    2375                     multiplier = 1;
    2376                     break;
    2377                 case `tick`:
    2378                 case `ticks`:
    2379                     compiler.next();
    2380                     multiplier = 10;
    2381                     break;
    2382                 case `second`:
    2383                 case `seconds`:
    2384                     compiler.next();
    2385                     multiplier = 1000;
    2386                     break;
    2387                 case `minute`:
    2388                 case `minutes`:
    2389                     compiler.next();
    2390                     multiplier = 60000;
    2391                     break;
     2403            case `milli`:
     2404            case `millis`:
     2405                compiler.next();
     2406                multiplier = 1;
     2407                break;
     2408            case `tick`:
     2409            case `ticks`:
     2410                compiler.next();
     2411                multiplier = 10;
     2412                break;
     2413            case `second`:
     2414            case `seconds`:
     2415                compiler.next();
     2416                multiplier = 1000;
     2417                break;
     2418            case `minute`:
     2419            case `minutes`:
     2420                compiler.next();
     2421                multiplier = 60000;
     2422                break;
    23922423            }
    23932424            compiler.addCommand({
     
    24552486    },
    24562487
    2457     getHandler: name => {
     2488    getHandler: (name) => {
    24582489        switch (name) {
    2459             case `add`:
    2460                 return EasyCoder_Core.Add;
    2461             case `alias`:
    2462                 return EasyCoder_Core.Alias;
    2463             case `append`:
    2464                 return EasyCoder_Core.Append;
    2465             case `begin`:
    2466                 return EasyCoder_Core.Begin;
    2467             case `callback`:
    2468                 return EasyCoder_Core.Callback;
    2469             case `clear`:
    2470                 return EasyCoder_Core.Clear;
    2471             case `close`:
    2472                 return EasyCoder_Core.Close;
    2473             case `debug`:
    2474                 return EasyCoder_Core.Debug;
    2475             case `decode`:
    2476                 return EasyCoder_Core.Decode;
    2477             case `divide`:
    2478                 return EasyCoder_Core.Divide;
    2479             case `dummy`:
    2480                 return EasyCoder_Core.Dummy;
    2481             case `encode`:
    2482                 return EasyCoder_Core.Encode;
    2483             case `end`:
    2484                 return EasyCoder_Core.End;
    2485             case `exit`:
    2486                 return EasyCoder_Core.Exit;
    2487             case `filter`:
    2488                 return EasyCoder_Core.Filter;
    2489             case `fork`:
    2490                 return EasyCoder_Core.Fork;
    2491             case `go`:
    2492             case `goto`:
    2493                 return EasyCoder_Core.Go;
    2494             case `gosub`:
    2495                 return EasyCoder_Core.Gosub;
    2496             case `if`:
    2497                 return EasyCoder_Core.If;
    2498             case `import`:
    2499                 return EasyCoder_Core.Import;
    2500             case `index`:
    2501                 return EasyCoder_Core.Index;
    2502             case `load`:
    2503                 return EasyCoder_Core.Load;
    2504             case `module`:
    2505                 return EasyCoder_Core.Module;
    2506             case `multiply`:
    2507                 return EasyCoder_Core.Multiply;
    2508             case `negate`:
    2509                 return EasyCoder_Core.Negate;
    2510             case `on`:
    2511                 return EasyCoder_Core.On;
    2512             case `print`:
    2513                 return EasyCoder_Core.Print;
    2514             case `put`:
    2515                 return EasyCoder_Core.Put;
    2516             case `replace`:
    2517                 return EasyCoder_Core.Replace;
    2518             case `require`:
    2519                 return EasyCoder_Core.Require;
    2520             case `return`:
    2521                 return EasyCoder_Core.Return;
    2522             case `run`:
    2523                 return EasyCoder_Core.Run;
    2524             case `sanitize`:
    2525                 return EasyCoder_Core.Sanitize;
    2526             case `script`:
    2527                 return EasyCoder_Core.Script;
    2528             case `send`:
    2529                 return EasyCoder_Core.Send;
    2530             case `set`:
    2531                 return EasyCoder_Core.Set;
    2532             case `sort`:
    2533                 return EasyCoder_Core.Sort;
    2534             case `stop`:
    2535                 return EasyCoder_Core.Stop;
    2536             case `take`:
    2537                 return EasyCoder_Core.Take;
    2538             case `toggle`:
    2539                 return EasyCoder_Core.Toggle;
    2540             case `variable`:
    2541                 return EasyCoder_Core.Variable;
    2542             case `wait`:
    2543                 return EasyCoder_Core.Wait;
    2544             case `while`:
    2545                 return EasyCoder_Core.While;
    2546             default:
    2547                 return false;
     2490        case `add`:
     2491            return EasyCoder_Core.Add;
     2492        case `alias`:
     2493            return EasyCoder_Core.Alias;
     2494        case `append`:
     2495            return EasyCoder_Core.Append;
     2496        case `begin`:
     2497            return EasyCoder_Core.Begin;
     2498        case `callback`:
     2499            return EasyCoder_Core.Callback;
     2500        case `clear`:
     2501            return EasyCoder_Core.Clear;
     2502        case `close`:
     2503            return EasyCoder_Core.Close;
     2504        case `debug`:
     2505            return EasyCoder_Core.Debug;
     2506        case `decode`:
     2507            return EasyCoder_Core.Decode;
     2508        case `divide`:
     2509            return EasyCoder_Core.Divide;
     2510        case `dummy`:
     2511            return EasyCoder_Core.Dummy;
     2512        case `encode`:
     2513            return EasyCoder_Core.Encode;
     2514        case `end`:
     2515            return EasyCoder_Core.End;
     2516        case `exit`:
     2517            return EasyCoder_Core.Exit;
     2518        case `filter`:
     2519            return EasyCoder_Core.Filter;
     2520        case `fork`:
     2521            return EasyCoder_Core.Fork;
     2522        case `go`:
     2523        case `goto`:
     2524            return EasyCoder_Core.Go;
     2525        case `gosub`:
     2526            return EasyCoder_Core.Gosub;
     2527        case `if`:
     2528            return EasyCoder_Core.If;
     2529        case `import`:
     2530            return EasyCoder_Core.Import;
     2531        case `index`:
     2532            return EasyCoder_Core.Index;
     2533        case `load`:
     2534            return EasyCoder_Core.Load;
     2535        case `module`:
     2536            return EasyCoder_Core.Module;
     2537        case `multiply`:
     2538            return EasyCoder_Core.Multiply;
     2539        case `negate`:
     2540            return EasyCoder_Core.Negate;
     2541        case `on`:
     2542            return EasyCoder_Core.On;
     2543        case `print`:
     2544            return EasyCoder_Core.Print;
     2545        case `put`:
     2546            return EasyCoder_Core.Put;
     2547        case `replace`:
     2548            return EasyCoder_Core.Replace;
     2549        case `require`:
     2550            return EasyCoder_Core.Require;
     2551        case `return`:
     2552            return EasyCoder_Core.Return;
     2553        case `run`:
     2554            return EasyCoder_Core.Run;
     2555        case `sanitize`:
     2556            return EasyCoder_Core.Sanitize;
     2557        case `script`:
     2558            return EasyCoder_Core.Script;
     2559        case `send`:
     2560            return EasyCoder_Core.Send;
     2561        case `set`:
     2562            return EasyCoder_Core.Set;
     2563        case `sort`:
     2564            return EasyCoder_Core.Sort;
     2565        case `split`:
     2566            return EasyCoder_Core.Split;
     2567        case `stop`:
     2568            return EasyCoder_Core.Stop;
     2569        case `take`:
     2570            return EasyCoder_Core.Take;
     2571        case `toggle`:
     2572            return EasyCoder_Core.Toggle;
     2573        case `variable`:
     2574            return EasyCoder_Core.Variable;
     2575        case `wait`:
     2576            return EasyCoder_Core.Wait;
     2577        case `while`:
     2578            return EasyCoder_Core.While;
     2579        default:
     2580            return false;
    25482581        }
    25492582    },
     
    25552588        const handler = EasyCoder_Core.getHandler(command.keyword);
    25562589        if (!handler) {
    2557             program.runtimeError(command.lino, `Unknown keyword '${command.keyword}' in 'core' package`);
     2590            program.runtimeError(command.lino,
     2591                `Unknown keyword '${command.keyword}' in 'core' package`);
    25582592        }
    25592593        return handler.run(program);
    25602594    },
    25612595
    2562     isNegate: compiler => {
     2596    isNegate: (compiler) => {
    25632597        const token = compiler.getToken();
    25642598        if (token === `not`) {
     
    25762610                const symbolRecord = compiler.getSymbolRecord();
    25772611                switch (symbolRecord.keyword) {
    2578                     case `module`:
    2579                         compiler.next();
     2612                case `module`:
     2613                    compiler.next();
     2614                    return {
     2615                        domain: `core`,
     2616                        type: `module`,
     2617                        name
     2618                    };
     2619                case `variable`:
     2620                    const type = compiler.nextToken();
     2621                    if ([`format`, `modulo`].includes(type)) {
     2622                        const value = compiler.getNextValue();
    25802623                        return {
    25812624                            domain: `core`,
    2582                             type: `module`,
    2583                             name
     2625                            type,
     2626                            name,
     2627                            value
    25842628                        };
    2585                     case `variable`:
    2586                         const type = compiler.nextToken();
    2587                         if ([`format`, `modulo`].includes(type)) {
    2588                             const value = compiler.getNextValue();
    2589                             return {
    2590                                 domain: `core`,
    2591                                 type,
    2592                                 name,
    2593                                 value
    2594                             };
    2595                         }
    2596                         return {
    2597                             domain: `core`,
    2598                             type: `symbol`,
    2599                             name
    2600                         };
     2629                    }
     2630                    return {
     2631                        domain: `core`,
     2632                        type: `symbol`,
     2633                        name
     2634                    };
    26012635                }
    26022636                return null;
     
    27402774                }
    27412775            }
     2776            if ([`character`, `char`].includes(token)) {
     2777                let index = compiler.getNextValue();
     2778                if (compiler.tokenIs(`of`)) {
     2779                    let value = compiler.getNextValue();
     2780                    return {
     2781                        domain: `core`,
     2782                        type: `char`,
     2783                        index,
     2784                        value
     2785                    };
     2786                }
     2787            }
    27422788            if (compiler.tokenIs(`the`)) {
    27432789                compiler.next();
     
    27452791            const type = compiler.getToken();
    27462792            switch (type) {
    2747                 case `elements`:
    2748                     if (compiler.nextTokenIs(`of`)) {
    2749                         if (compiler.nextIsSymbol()) {
     2793            case `elements`:
     2794                if (compiler.nextTokenIs(`of`)) {
     2795                    if (compiler.nextIsSymbol()) {
     2796                        const name = compiler.getToken();
     2797                        compiler.next();
     2798                        return {
     2799                            domain: `core`,
     2800                            type,
     2801                            name
     2802                        };
     2803                    }
     2804                }
     2805                break;
     2806            case `index`:
     2807                if (compiler.nextTokenIs(`of`)) {
     2808                    if (compiler.nextIsSymbol()) {
     2809                        if (compiler.peek() === `in`) {
     2810                            const value1 = compiler.getValue();
     2811                            const value2 = compiler.getNextValue();
     2812                            return {
     2813                                domain: `core`,
     2814                                type: `indexOf`,
     2815                                value1,
     2816                                value2
     2817                            };
     2818                        } else {
    27502819                            const name = compiler.getToken();
    27512820                            compiler.next();
     
    27562825                            };
    27572826                        }
    2758                     }
    2759                     break;
    2760                 case `index`:
    2761                     if (compiler.nextTokenIs(`of`)) {
    2762                         if (compiler.nextIsSymbol()) {
    2763                             if (compiler.peek() === `in`) {
    2764                                 const value1 = compiler.getValue();
    2765                                 const value2 = compiler.getNextValue();
    2766                                 return {
    2767                                     domain: `core`,
    2768                                     type: `indexOf`,
    2769                                     value1,
    2770                                     value2
    2771                                 };
    2772                             } else {
    2773                                 const name = compiler.getToken();
    2774                                 compiler.next();
    2775                                 return {
    2776                                     domain: `core`,
    2777                                     type,
    2778                                     name
    2779                                 };
    2780                             }
    2781                         } else {
    2782                             const value1 = compiler.getValue();
    2783                             if (compiler.tokenIs(`in`)) {
    2784                                 const value2 = compiler.getNextValue();
    2785                                 return {
    2786                                     domain: `core`,
    2787                                     type: `indexOf`,
    2788                                     value1,
    2789                                     value2
    2790                                 };
    2791                             }
    2792                         }
    2793                     }
    2794                     break;
    2795                 case `value`:
    2796                     if (compiler.nextTokenIs(`of`)) {
    2797                         compiler.next();
    2798                         const value = compiler.getValue();
    2799                         return {
    2800                             domain: `core`,
    2801                             type: `valueOf`,
    2802                             value
    2803                         };
    2804                     }
    2805                     break;
    2806                 case `length`:
    2807                     if (compiler.nextTokenIs(`of`)) {
    2808                         compiler.next();
    2809                         const value = compiler.getValue();
    2810                         return {
    2811                             domain: `core`,
    2812                             type: `lengthOf`,
    2813                             value
    2814                         };
    2815                     }
    2816                     break;
    2817                 case `left`:
    2818                 case `right`:
    2819                     try {
    2820                         const count = compiler.getNextValue();
    2821                         if (compiler.tokenIs(`of`)) {
    2822                             const value = compiler.getNextValue();
     2827                    } else {
     2828                        const value1 = compiler.getValue();
     2829                        if (compiler.tokenIs(`in`)) {
     2830                            const value2 = compiler.getNextValue();
    28232831                            return {
    28242832                                domain: `core`,
    2825                                 type,
    2826                                 count,
    2827                                 value
     2833                                type: `indexOf`,
     2834                                value1,
     2835                                value2
    28282836                            };
    28292837                        }
    2830                     } catch (err) {
    2831                         return null;
    2832                     }
    2833                     break;
    2834                 case `from`:
    2835                     const from = compiler.getNextValue();
    2836                     const to = compiler.tokenIs(`to`) ? compiler.getNextValue() : null;
     2838                    }
     2839                }
     2840                break;
     2841            case `value`:
     2842                if (compiler.nextTokenIs(`of`)) {
     2843                    compiler.next();
     2844                    const value = compiler.getValue();
     2845                    return {
     2846                        domain: `core`,
     2847                        type: `valueOf`,
     2848                        value
     2849                    };
     2850                }
     2851                break;
     2852            case `length`:
     2853                if (compiler.nextTokenIs(`of`)) {
     2854                    compiler.next();
     2855                    const value = compiler.getValue();
     2856                    return {
     2857                        domain: `core`,
     2858                        type: `lengthOf`,
     2859                        value
     2860                    };
     2861                }
     2862                break;
     2863            case `left`:
     2864            case `right`:
     2865                try {
     2866                    const count = compiler.getNextValue();
    28372867                    if (compiler.tokenIs(`of`)) {
    28382868                        const value = compiler.getNextValue();
     
    28402870                            domain: `core`,
    28412871                            type,
    2842                             from,
    2843                             to,
     2872                            count,
    28442873                            value
    28452874                        };
    28462875                    }
    2847                     break;
    2848                 case `position`:
    2849                     if (compiler.nextTokenIs(`of`)) {
    2850                         var last = false;
    2851                         if (compiler.nextTokenIs(`the`)) {
    2852                             if (compiler.nextTokenIs(`last`)) {
    2853                                 compiler.next();
    2854                                 last = true;
    2855                             }
     2876                } catch (err) {
     2877                    return null;
     2878                }
     2879                break;
     2880            case `from`:
     2881                const from = compiler.getNextValue();
     2882                const to = compiler.tokenIs(`to`) ? compiler.getNextValue() : null;
     2883                if (compiler.tokenIs(`of`)) {
     2884                    const value = compiler.getNextValue();
     2885                    return {
     2886                        domain: `core`,
     2887                        type,
     2888                        from,
     2889                        to,
     2890                        value
     2891                    };
     2892                }
     2893                break;
     2894            case `position`:
     2895                let nocase = false;
     2896                if (compiler.nextTokenIs(`nocase`)) {
     2897                    nocase = true;
     2898                    compiler.next();
     2899                }
     2900                if (compiler.tokenIs(`of`)) {
     2901                    var last = false;
     2902                    if (compiler.nextTokenIs(`the`)) {
     2903                        if (compiler.nextTokenIs(`last`)) {
     2904                            compiler.next();
     2905                            last = true;
    28562906                        }
    2857                         const needle = compiler.getValue();
    2858                         if (compiler.tokenIs(`in`)) {
    2859                             const haystack = compiler.getNextValue();
     2907                    }
     2908                    const needle = compiler.getValue();
     2909                    if (compiler.tokenIs(`in`)) {
     2910                        const haystack = compiler.getNextValue();
     2911                        return {
     2912                            domain: `core`,
     2913                            type: `position`,
     2914                            needle,
     2915                            haystack,
     2916                            last,
     2917                            nocase
     2918                        };
     2919                    }
     2920                }
     2921                break;
     2922            case `payload`:
     2923                if (compiler.nextTokenIs(`of`)) {
     2924                    if (compiler.nextIsSymbol()) {
     2925                        const callbackRecord = compiler.getSymbolRecord();
     2926                        if (callbackRecord.keyword === `callback`) {
     2927                            compiler.next();
    28602928                            return {
    28612929                                domain: `core`,
    2862                                 type: `position`,
    2863                                 needle,
    2864                                 haystack,
    2865                                 last
     2930                                type: `payload`,
     2931                                callback: callbackRecord.name
    28662932                            };
    28672933                        }
    28682934                    }
    2869                     break;
    2870                 case `payload`:
    2871                     if (compiler.nextTokenIs(`of`)) {
    2872                         if (compiler.nextIsSymbol()) {
    2873                             const callbackRecord = compiler.getSymbolRecord();
    2874                             if (callbackRecord.keyword === `callback`) {
    2875                                 compiler.next();
    2876                                 return {
    2877                                     domain: `core`,
    2878                                     type: `payload`,
    2879                                     callback: callbackRecord.name
    2880                                 };
    2881                             }
    2882                         }
    2883                     }
    2884                     break;
    2885                 case `message`:
    2886                 case `error`:
    2887                     compiler.next();
    2888                     return {
    2889                         domain: `core`,
    2890                         type
    2891                     };
     2935                }
     2936                break;
     2937            case `message`:
     2938            case `error`:
     2939                compiler.next();
     2940                return {
     2941                    domain: `core`,
     2942                    type
     2943                };
    28922944            }
    28932945            return null;
     
    28962948        get: (program, value) => {
    28972949            switch (value.type) {
    2898                 case `boolean`:
    2899                     return {
    2900                         type: `boolean`,
    2901                         numeric: false,
    2902                         content: value.content
    2903                     };
    2904                 case `elements`:
    2905                     return {
    2906                         type: `constant`,
    2907                         numeric: true,
    2908                         content: program.getSymbolRecord(value.name).elements
    2909                     };
    2910                 case `index`:
    2911                     return {
    2912                         type: `constant`,
    2913                         numeric: true,
    2914                         content: program.getSymbolRecord(value.name).index
    2915                     };
    2916                 case `random`:
    2917                     const range = program.evaluate(value.range);
    2918                     return {
    2919                         type: `constant`,
    2920                         numeric: true,
    2921                         content: Math.floor(Math.random() * range.content)
    2922                     };
    2923                 case `cos`:
    2924                     const angle_c = program.getValue(value.angle_c);
    2925                     const radius_c = program.getValue(value.radius_c);
    2926                     return {
    2927                         type: `constant`,
    2928                         numeric: true,
    2929                         content: parseInt(Math.cos(parseFloat(angle_c) * 0.01745329) * radius_c, 10)
    2930                     };
    2931                 case `sin`:
    2932                     const angle_s = program.getValue(value.angle_s);
    2933                     const radius_s = program.getValue(value.radius_s);
    2934                     return {
    2935                         type: `constant`,
    2936                         numeric: true,
    2937                         content: parseInt(Math.sin(parseFloat(angle_s) * 0.01745329) * radius_s, 10)
    2938                     };
    2939                 case `tan`:
    2940                     const angle_t = program.getValue(value.angle_t);
    2941                     const radius_t = program.getValue(value.radius_t);
    2942                     return {
    2943                         type: `constant`,
    2944                         numeric: true,
    2945                         content: parseInt(Math.tan(parseFloat(angle_t) * 0.01745329) * radius_t, 10)
    2946                     };
    2947                 case `valueOf`:
    2948                     const v = parseInt(program.getValue(value.value));
    2949                     return {
    2950                         type: `constant`,
    2951                         numeric: true,
    2952                         content: v ? v : 0
    2953                     };
    2954                 case `lengthOf`:
    2955                     return {
    2956                         type: `constant`,
    2957                         numeric: true,
    2958                         content: program.getValue(value.value).length
    2959                     };
    2960                 case `left`:
    2961                     return {
    2962                         type: `constant`,
    2963                         numeric: false,
    2964                         content: program.getValue(value.value).substr(0, program.getValue(value.count))
    2965                     };
    2966                 case `right`:
    2967                     const str = program.getValue(value.value);
    2968                     return {
    2969                         type: `constant`,
    2970                         numeric: false,
    2971                         content: str.substr(str.length - program.getValue(value.count))
    2972                     };
    2973                 case `from`:
    2974                     const from = program.getValue(value.from);
    2975                     const to = value.to ? program.getValue(value.to) : null;
    2976                     const fstr = program.getValue(value.value);
    2977                     return {
    2978                         type: `constant`,
    2979                         numeric: false,
    2980                         content: to ? fstr.substr(from, to) : fstr.substr(from)
    2981                     };
    2982                 case `position`:
    2983                     const needle = program.getValue(value.needle);
    2984                     const haystack = program.getValue(value.haystack);
    2985                     return {
    2986                         type: `constant`,
    2987                         numeric: true,
    2988                         content: value.last ? haystack.lastIndexOf(needle) : haystack.indexOf(needle)
    2989                     };
    2990                 case `payload`:
    2991                     return {
    2992                         type: `constant`,
    2993                         numeric: false,
    2994                         content: program.getSymbolRecord(value.callback).payload
    2995                     };
    2996                 case `modulo`:
    2997                     const symbolRecord = program.getSymbolRecord(value.name);
    2998                     const modval = program.evaluate(value.value);
    2999                     return {
    3000                         type: `constant`,
    3001                         numeric: true,
    3002                         content: symbolRecord.value[symbolRecord.index].content % modval.content
    3003                     };
    3004                 case `format`:
    3005                     const fmtRecord = program.getSymbolRecord(value.name);
    3006                     const fmtValue = program.getValue(fmtRecord.value[fmtRecord.index]) * 1000;
    3007                     try {
    3008                         const spec = JSON.parse(program.getValue(value.value));
    3009                         switch (spec.mode) {
    3010                             case `time`:
    3011                                 return {
    3012                                     type: `constant`,
    3013                                     numeric: true,
    3014                                     content: new Date(fmtValue).toLocaleTimeString(spec.locale, spec.options)
    3015                                 };
    3016                             case `date`:
    3017                             default:
    3018                                 return {
    3019                                     type: `constant`,
    3020                                     numeric: true,
    3021                                     content: new Date(fmtValue).toLocaleDateString(spec.locale, spec.options)
    3022                                 };
    3023                         }
    3024                     } catch (err) {
    3025                         program.runtimeError(program[program.pc].lino, `Can't parse ${value.value}`);
    3026                         return null;
    3027                     }
    3028                 case `empty`:
    3029                     return {
    3030                         type: `constant`,
    3031                         numeric: false,
    3032                         content: ``
    3033                     };
    3034                 case `now`:
    3035                     return {
    3036                         type: `constant`,
    3037                         numeric: true,
    3038                         content: Math.floor(Date.now() / 1000)
    3039                     };
    3040                 case `today`:
    3041                     const date = new Date();
    3042                     date.setHours(0, 0, 0, 0);
    3043                     return {
    3044                         type: `constant`,
    3045                         numeric: true,
    3046                         content: Math.floor(date.getTime() / 1000)
    3047                     };
    3048                 case `date`:
    3049                     return {
    3050                         type: `constant`,
    3051                         numeric: true,
    3052                         content: Date.parse(program.getValue(value.value)) / 1000
    3053                     };
    3054                 case `newline`:
    3055                     return {
    3056                         type: `constant`,
    3057                         numeric: false,
    3058                         content: `\n`
    3059                     };
    3060                 case `break`:
    3061                     return {
    3062                         type: `constant`,
    3063                         numeric: false,
    3064                         content: `<br />`
    3065                     };
    3066                 case `encode`:
    3067                     return {
    3068                         type: `constant`,
    3069                         numeric: false,
    3070                         content: program.encode(program.getValue(value.value))
    3071                     };
    3072                 case `decode`:
    3073                     return {
    3074                         type: `constant`,
    3075                         numeric: false,
    3076                         content: program.decode(program.getValue(value.value))
    3077                     };
    3078                 case `lowercase`:
    3079                     return {
    3080                         type: `constant`,
    3081                         numeric: false,
    3082                         content: program.getValue(value.value).toLowerCase()
    3083                     };
    3084                 case `hash`:
    3085                     const hashval = program.getValue(value.value);
    3086                     let hash = 0;
    3087                     if (hashval.length === 0) return hash;
    3088                     for (let i = 0; i < hashval.length; i++) {
    3089                         const chr = hashval.charCodeAt(i);
    3090                         hash = (hash << 5) - hash + chr;
    3091                         //                  hash |= 0; // Convert to 32bit integer
    3092                     }
    3093                     return {
    3094                         type: `constant`,
    3095                         numeric: true,
    3096                         content: hash
    3097                     };
    3098                 case `element`:
    3099                     const element = program.getValue(value.element);
    3100                     const elementRecord = program.getSymbolRecord(value.symbol);
    3101                     var elementContent = ``;
    3102                     try {
    3103                         elementContent = JSON.parse(program.getValue(elementRecord.value[elementRecord.index]))[element];
    3104                     } catch (err) {
    3105                         program.runtimeError(program[program.pc].lino, `Can't parse JSON`);
    3106                         return null;
    3107                     }
    3108                     return {
    3109                         type: `constant`,
    3110                         numeric: false,
    3111                         content: typeof elementContent === `object` ? JSON.stringify(elementContent) : elementContent
    3112                     };
    3113                 case `property`:
    3114                     const property = program.getValue(value.property);
    3115                     const propertyRecord = program.getSymbolRecord(value.symbol);
    3116                     let propertyContent = program.getValue(propertyRecord.value[propertyRecord.index]);
    3117                     var content = ``;
    3118                     if (property && propertyContent) {
    3119                         if (typeof propertyContent === `object`) {
    3120                             content = propertyContent[property];
    3121                         } else if (propertyContent.charAt(0) === `{`) {
    3122                             try {
    3123                                 content = JSON.parse(propertyContent)[property];
    3124                             } catch (err) {
    3125                                 console.log(`Can't parse '${propertyContent}': ${err.message}`);
    3126                             }
    3127                         }
    3128                     }
    3129                     return {
    3130                         type: `constant`,
    3131                         numeric: !isNaN(content),
    3132                         content: typeof content === `object` ? JSON.stringify(content) : content
    3133                     };
    3134                 case `module`:
    3135                     const module = program.getSymbolRecord(value.name);
    3136                     return {
    3137                         type: `boolean`,
    3138                         numeric: false,
    3139                         content: module.program
    3140                     };
    3141                 case `message`:
    3142                     content = program.message;
    3143                     return {
    3144                         type: `constant`,
    3145                         numeric: false,
    3146                         content
    3147                     };
    3148                 case `error`:
    3149                     content = program.errorMessage;
    3150                     return {
    3151                         type: `constant`,
    3152                         numeric: false,
    3153                         content
    3154                     };
    3155                 case `indexOf`:
    3156                     const value1 = program.getValue(value.value1);
    3157                     const value2 = program.getValue(value.value2);
    3158                     try {
    3159                         content = JSON.parse(value2).indexOf(value1);
     2950            case `boolean`:
     2951                return {
     2952                    type: `boolean`,
     2953                    numeric: false,
     2954                    content: value.content
     2955                };
     2956            case `elements`:
     2957                return {
     2958                    type: `constant`,
     2959                    numeric: true,
     2960                    content: program.getSymbolRecord(value.name).elements
     2961                };
     2962            case `index`:
     2963                return {
     2964                    type: `constant`,
     2965                    numeric: true,
     2966                    content: program.getSymbolRecord(value.name).index
     2967                };
     2968            case `random`:
     2969                const range = program.evaluate(value.range);
     2970                return {
     2971                    type: `constant`,
     2972                    numeric: true,
     2973                    content: Math.floor((Math.random() * range.content))
     2974                };
     2975            case `cos`:
     2976                const angle_c = program.getValue(value.angle_c);
     2977                const radius_c = program.getValue(value.radius_c);
     2978                return {
     2979                    type: `constant`,
     2980                    numeric: true,
     2981                    content: parseInt(Math.cos(parseFloat(angle_c) * 0.01745329) * radius_c, 10)
     2982                };
     2983            case `sin`:
     2984                const angle_s = program.getValue(value.angle_s);
     2985                const radius_s = program.getValue(value.radius_s);
     2986                return {
     2987                    type: `constant`,
     2988                    numeric: true,
     2989                    content: parseInt(Math.sin(parseFloat(angle_s) * 0.01745329) * radius_s, 10)
     2990                };
     2991            case `tan`:
     2992                const angle_t = program.getValue(value.angle_t);
     2993                const radius_t = program.getValue(value.radius_t);
     2994                return {
     2995                    type: `constant`,
     2996                    numeric: true,
     2997                    content: parseInt(Math.tan(parseFloat(angle_t) * 0.01745329) * radius_t, 10)
     2998                };
     2999            case `valueOf`:
     3000                const v = parseInt(program.getValue(value.value));
     3001                return {
     3002                    type: `constant`,
     3003                    numeric: true,
     3004                    content: v ? v : 0
     3005                };
     3006            case `lengthOf`:
     3007                return {
     3008                    type: `constant`,
     3009                    numeric: true,
     3010                    content: program.getValue(value.value).length
     3011                };
     3012            case `left`:
     3013                return {
     3014                    type: `constant`,
     3015                    numeric: false,
     3016                    content: program.getValue(value.value).substr(0, program.getValue(value.count))
     3017                };
     3018            case `right`:
     3019                const str = program.getValue(value.value);
     3020                return {
     3021                    type: `constant`,
     3022                    numeric: false,
     3023                    content: str.substr(str.length - program.getValue(value.count))
     3024                };
     3025            case `from`:
     3026                const from = program.getValue(value.from);
     3027                const to = value.to ? program.getValue(value.to) : null;
     3028                const fstr = program.getValue(value.value);
     3029                return {
     3030                    type: `constant`,
     3031                    numeric: false,
     3032                    content: to ? fstr.substr(from, to) : fstr.substr(from)
     3033                };
     3034            case `position`:
     3035                let needle = program.getValue(value.needle);
     3036                let haystack = program.getValue(value.haystack);
     3037                if (value.nocase) {
     3038                    needle = needle.toLowerCase();
     3039                    haystack = haystack.toLowerCase();
     3040                }
     3041                return {
     3042                    type: `constant`,
     3043                    numeric: true,
     3044                    content: value.last ? haystack.lastIndexOf(needle) : haystack.indexOf(needle)
     3045                };
     3046            case `payload`:
     3047                return {
     3048                    type: `constant`,
     3049                    numeric: false,
     3050                    content: program.getSymbolRecord(value.callback).payload
     3051                };
     3052            case `modulo`:
     3053                const symbolRecord = program.getSymbolRecord(value.name);
     3054                const modval = program.evaluate(value.value);
     3055                return {
     3056                    type: `constant`,
     3057                    numeric: true,
     3058                    content: symbolRecord.value[symbolRecord.index].content % modval.content
     3059                };
     3060            case `format`:
     3061                const fmtRecord = program.getSymbolRecord(value.name);
     3062                const fmtValue = program.getValue(fmtRecord.value[fmtRecord.index]) * 1000;
     3063                try {
     3064                    const spec = JSON.parse(program.getValue(value.value));
     3065                    switch (spec.mode) {
     3066                    case `time`:
     3067                       
     3068                        return {
     3069                            type: `constant`,
     3070                            numeric: true,
     3071                            content: new Date(fmtValue).toLocaleTimeString(spec.locale, spec.options)
     3072                        };
     3073                    case `date`:
     3074                    default:
     3075                        const date = new Date(fmtValue);
     3076                        const content = (spec.format === `iso`)
     3077                            ? `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`
     3078                            : date.toLocaleDateString(spec.locale, spec.options);
    31603079                        return {
    31613080                            type: `constant`,
     
    31633082                            content
    31643083                        };
    3165                     } catch (err) {
    3166                         program.runtimeError(program[program.pc].lino, `Can't parse ${value2}`);
    3167                     }
    3168                     break;
    3169                 case `arg`:
    3170                     const name = program.getValue(value.value);
    3171                     const target = program.getSymbolRecord(value.target);
    3172                     content = target[name];
     3084                    }
     3085                } catch (err) {
     3086                    program.runtimeError(program[program.pc].lino, `Can't parse ${value.value}`);
     3087                    return null;
     3088                }
     3089            case `empty`:
     3090                return {
     3091                    type: `constant`,
     3092                    numeric: false,
     3093                    content: ``
     3094                };
     3095            case `now`:
     3096                return {
     3097                    type: `constant`,
     3098                    numeric: true,
     3099                    content: Math.floor(Date.now() / 1000)
     3100                };
     3101            case `today`:
     3102                const date = new Date();
     3103                date.setHours(0, 0, 0, 0);
     3104                return {
     3105                    type: `constant`,
     3106                    numeric: true,
     3107                    content: Math.floor(date.getTime() / 1000)
     3108                };
     3109            case `date`:
     3110                content = Date.parse(program.getValue(value.value)) / 1000;
     3111                if (isNaN(content)) {
     3112                    program.runtimeError(program[program.pc].lino, `Invalid date format; expecting 'yyyy-mm-dd'`);
     3113                    return null;
     3114                }
     3115                return {
     3116                    type: `constant`,
     3117                    numeric: true,
     3118                    content
     3119                };
     3120            case `newline`:
     3121                return {
     3122                    type: `constant`,
     3123                    numeric: false,
     3124                    content: `\n`
     3125                };
     3126            case `break`:
     3127                return {
     3128                    type: `constant`,
     3129                    numeric: false,
     3130                    content: `<br />`
     3131                };
     3132            case `encode`:
     3133                return {
     3134                    type: `constant`,
     3135                    numeric: false,
     3136                    content: program.encode(program.getValue(value.value))
     3137                };
     3138            case `decode`:
     3139                return {
     3140                    type: `constant`,
     3141                    numeric: false,
     3142                    content: program.decode(program.getValue(value.value))
     3143                };
     3144            case `lowercase`:
     3145                return {
     3146                    type: `constant`,
     3147                    numeric: false,
     3148                    content: program.getValue(value.value).toLowerCase()
     3149                };
     3150            case `hash`:
     3151                const hashval = program.getValue(value.value);
     3152                let hash = 0;
     3153                if (hashval.length === 0) return hash;
     3154                for (let i = 0; i < hashval.length; i++) {
     3155                    const chr = hashval.charCodeAt(i);
     3156                    hash = ((hash << 5) - hash) + chr;
     3157                    //                  hash |= 0; // Convert to 32bit integer
     3158                }
     3159                return {
     3160                    type: `constant`,
     3161                    numeric: true,
     3162                    content: hash
     3163                };
     3164            case `element`:
     3165                const element = program.getValue(value.element);
     3166                const elementRecord = program.getSymbolRecord(value.symbol);
     3167                var elementContent = ``;
     3168                try {
     3169                    elementContent = JSON.parse(program.getValue(elementRecord.value[elementRecord.index]))[element];
     3170                } catch (err) {
     3171                    program.runtimeError(program[program.pc].lino, `Can't parse JSON`);
     3172                    return null;
     3173                }
     3174                return {
     3175                    type: `constant`,
     3176                    numeric: false,
     3177                    content: typeof elementContent === `object` ?
     3178                        JSON.stringify(elementContent) : elementContent
     3179                };
     3180            case `property`:
     3181                const property = program.getValue(value.property);
     3182                const propertyRecord = program.getSymbolRecord(value.symbol);
     3183                let propertyContent = program.getValue(propertyRecord.value[propertyRecord.index]);
     3184                var content = ``;
     3185                if (property && propertyContent) {
     3186                    if (typeof propertyContent === `object`) {
     3187                        content = propertyContent[property];
     3188                    } else if (propertyContent.charAt(0) === `{`) {
     3189                        try {
     3190                            content = JSON.parse(propertyContent)[property];
     3191                        } catch (err) {
     3192                            console.log(`Can't parse '${propertyContent}': ${err.message}`);
     3193                        }
     3194                    }
     3195                }
     3196                return {
     3197                    type: `constant`,
     3198                    numeric: !isNaN(content),
     3199                    content: typeof content === `object` ? JSON.stringify(content) : content
     3200                };
     3201            case `module`:
     3202                const module = program.getSymbolRecord(value.name);
     3203                return {
     3204                    type: `boolean`,
     3205                    numeric: false,
     3206                    content: module.program
     3207                };
     3208            case `message`:
     3209                content = program.message;
     3210                return {
     3211                    type: `constant`,
     3212                    numeric: false,
     3213                    content
     3214                };
     3215            case `error`:
     3216                content = program.errorMessage;
     3217                return {
     3218                    type: `constant`,
     3219                    numeric: false,
     3220                    content
     3221                };
     3222            case `indexOf`:
     3223                const value1 = program.getValue(value.value1);
     3224                const value2 = program.getValue(value.value2);
     3225                try {
     3226                    content = JSON.parse(value2).indexOf(value1);
    31733227                    return {
    31743228                        type: `constant`,
    3175                         numeric: !isNaN(content),
     3229                        numeric: true,
    31763230                        content
    31773231                    };
     3232                } catch (err) {
     3233                    program.runtimeError(program[program.pc].lino, `Can't parse ${value2}`);
     3234                }
     3235                break;
     3236            case `arg`:
     3237                const name = program.getValue(value.value);
     3238                const target = program.getSymbolRecord(value.target);
     3239                content = target[name];
     3240                return {
     3241                    type: `constant`,
     3242                    numeric: !isNaN(content),
     3243                    content
     3244                };
     3245            case `char`:
     3246                let index = program.getValue(value.index);
     3247                let string = program.getValue(value.value);
     3248                return {
     3249                    type: `constant`,
     3250                    numeric: false,
     3251                    content: string[index]
     3252                };
    31783253            }
    31793254            return null;
     
    32353310                    const test = compiler.getToken();
    32363311                    switch (test) {
    3237                         case `numeric`:
     3312                    case `numeric`:
     3313                        compiler.next();
     3314                        return {
     3315                            domain: `core`,
     3316                            type: `numeric`,
     3317                            value1,
     3318                            negate
     3319                        };
     3320                    case `even`:
     3321                        compiler.next();
     3322                        return {
     3323                            domain: `core`,
     3324                            type: `even`,
     3325                            value1
     3326                        };
     3327                    case `odd`:
     3328                        compiler.next();
     3329                        return {
     3330                            domain: `core`,
     3331                            type: `odd`,
     3332                            value1
     3333                        };
     3334                    case `greater`:
     3335                        compiler.next();
     3336                        if (compiler.tokenIs(`than`)) {
    32383337                            compiler.next();
    3239                             return {
    3240                                 domain: `core`,
    3241                                 type: `numeric`,
    3242                                 value1
    3243                             };
    3244                         case `even`:
    3245                             compiler.next();
    3246                             return {
    3247                                 domain: `core`,
    3248                                 type: `even`,
    3249                                 value1
    3250                             };
    3251                         case `odd`:
    3252                             compiler.next();
    3253                             return {
    3254                                 domain: `core`,
    3255                                 type: `odd`,
    3256                                 value1
    3257                             };
    3258                         case `greater`:
    3259                             compiler.next();
    3260                             if (compiler.tokenIs(`than`)) {
    3261                                 compiler.next();
    3262                                 const value2 = compiler.getValue();
    3263                                 return {
    3264                                     domain: `core`,
    3265                                     type: `greater`,
    3266                                     value1,
    3267                                     value2,
    3268                                     negate
    3269                                 };
    3270                             }
    3271                             return null;
    3272                         case `less`:
    3273                             compiler.next();
    3274                             if (compiler.tokenIs(`than`)) {
    3275                                 compiler.next();
    3276                                 const value2 = compiler.getValue();
    3277                                 return {
    3278                                     domain: `core`,
    3279                                     type: `less`,
    3280                                     value1,
    3281                                     value2,
    3282                                     negate
    3283                                 };
    3284                             }
    3285                             return null;
    3286                         default:
    32873338                            const value2 = compiler.getValue();
    32883339                            return {
    32893340                                domain: `core`,
    3290                                 type: `is`,
     3341                                type: `greater`,
    32913342                                value1,
    32923343                                value2,
    32933344                                negate
    32943345                            };
     3346                        }
     3347                        return null;
     3348                    case `less`:
     3349                        compiler.next();
     3350                        if (compiler.tokenIs(`than`)) {
     3351                            compiler.next();
     3352                            const value2 = compiler.getValue();
     3353                            return {
     3354                                domain: `core`,
     3355                                type: `less`,
     3356                                value1,
     3357                                value2,
     3358                                negate
     3359                            };
     3360                        }
     3361                        return null;
     3362                    default:
     3363                        const value2 = compiler.getValue();
     3364                        return {
     3365                            domain: `core`,
     3366                            type: `is`,
     3367                            value1,
     3368                            value2,
     3369                            negate
     3370                        };
    32953371                    }
    32963372                } else if (value1) {
     
    33123388            var comparison;
    33133389            switch (condition.type) {
    3314                 case `boolean`:
    3315                     return program.getValue(condition.value);
    3316                 case `numeric`:
    3317                     return !isNaN(program.getValue(condition.value1));
    3318                 case `even`:
    3319                     return program.getValue(condition.value1) % 2 === 0;
    3320                 case `odd`:
    3321                     return program.getValue(condition.value1) % 2 === 1;
    3322                 case `is`:
    3323                     comparison = program.compare(program, condition.value1, condition.value2);
    3324                     return condition.negate ? comparison !== 0 : comparison === 0;
    3325                 case `greater`:
    3326                     comparison = program.compare(program, condition.value1, condition.value2);
    3327                     return condition.negate ? comparison <= 0 : comparison > 0;
    3328                 case `less`:
    3329                     comparison = program.compare(program, condition.value1, condition.value2);
    3330                     return condition.negate ? comparison >= 0 : comparison < 0;
    3331                 case `not`:
    3332                     return !program.getValue(condition.value);
    3333                 case `moduleRunning`:
    3334                     const running = program.getSymbolRecord(condition.name).program;
    3335                     return condition.sense ? running : !running;
    3336                 case `includes`:
    3337                     const value1 = JSON.parse(program.getValue(condition.value1));
    3338                     const value2 = program.getValue(condition.value2);
    3339                     return value1.includes(value2);
     3390            case `boolean`:
     3391                return program.getValue(condition.value);
     3392            case `numeric`:
     3393                let v = program.getValue(condition.value1);
     3394                let test = v === ` ` || isNaN(v);
     3395                return condition.negate ? test : !test;
     3396            case `even`:
     3397                return (program.getValue(condition.value1) % 2) === 0;
     3398            case `odd`:
     3399                return (program.getValue(condition.value1) % 2) === 1;
     3400            case `is`:
     3401                comparison = program.compare(program, condition.value1, condition.value2);
     3402                return condition.negate ? comparison !== 0 : comparison === 0;
     3403            case `greater`:
     3404                comparison = program.compare(program, condition.value1, condition.value2);
     3405                return condition.negate ? comparison <= 0 : comparison > 0;
     3406            case `less`:
     3407                comparison = program.compare(program, condition.value1, condition.value2);
     3408                return condition.negate ? comparison >= 0 : comparison < 0;
     3409            case `not`:
     3410                return !program.getValue(condition.value);
     3411            case `moduleRunning`:
     3412                const running = program.getSymbolRecord(condition.name).program;
     3413                return condition.sense ? running : !running;
     3414            case `includes`:
     3415                const value1 = JSON.parse(program.getValue(condition.value1));
     3416                const value2 = program.getValue(condition.value2);
     3417                return value1.includes(value2);
    33403418            }
    33413419            return false;
     
    33433421    }
    33443422};
    3345 
    3346 module.exports = EasyCoder_Core;
    3347 },{}],6:[function(require,module,exports){
    3348 var _this = this;
    3349 
    3350 const EasyCoder_Compiler = require(`./Compile`);
    3351 const EasyCoder_Run = require(`./Run`);
    3352 const EasyCoder_Value = require(`./Value`);
    3353 const EasyCoder_Condition = require(`./Condition`);
    3354 const EasyCoder_Compare = require(`./Compare`);
    3355 const EasyCoder_Core = require(`./Core`);
    3356 
    33573423const EasyCoder = {
     3424
     3425    name: `EasyCoder_Main`,
    33583426
    33593427    domain: {
     
    33643432        this.lino = lino;
    33653433        this.reportError({
    3366             message: `Line ${lino >= 0 ? lino : ``}: ${message}`
    3367         }, EasyCoder.program);
    3368         EasyCoder.program.aborted = true;
     3434            message: `Line ${(lino >= 0) ? lino : ``}: ${message}`
     3435        }, this.program);
     3436        this.program.aborted = true;
    33693437    },
    33703438    nonNumericValueError: function (lino) {
     
    33863454            return;
    33873455        }
    3388         const compiler = EasyCoder_Compiler;
     3456        // const compiler = EasyCoder_Compiler;
    33893457        const {
    33903458            tokens,
    33913459            scriptLines
    33923460        } = source ? source : program.source;
    3393         const lino = this.compiling ? tokens[compiler.getIndex()].lino : program[program.pc].lino;
     3461        const lino = this.compiling ? tokens[EasyCoder_Compiler.getIndex()].lino : program[program.pc].lino;
    33943462        var errString = this.compiling ? `Compile error` : `Runtime error in '${program.script}'`;
    33953463        errString += `:\n`;
     
    34183486        }
    34193487        if (target.exporter) {
    3420             if (target.exporter != this) {
    3421                 return target.exporter.getSymbolRecord(target.exportedName);
    3422             }
     3488            // if (target.exporter != this.script) {
     3489            return EasyCoder.scripts[target.exporter].getSymbolRecord(target.exportedName);
     3490            // }
    34233491        }
    34243492        return target;
     
    34533521            return v.content ? `true` : `false`;
    34543522        }
    3455         if (v.content.substr(0, 2) === `{"` || v.content[0] === `[`) {
     3523        if (typeof v.content !==`undefined` && v.content.length >= 2
     3524            && (v.content.substr(0, 2) === `{"` || v.content[0] === `[`)) {
    34563525            try {
    34573526                const parsed = JSON.parse(v.content);
     
    34813550    run: function (pc) {
    34823551        if (pc) {
    3483             EasyCoder.program = this;
     3552            this.program = this;
    34843553            EasyCoder_Run.run(this, pc);
    34853554        }
     
    34903559    },
    34913560
    3492     register: program => {
    3493         EasyCoder.program = program;
    3494     },
    3495 
    3496     require: (type, src, cb) => {
     3561    register: (program) => {
     3562        this.program = program;
     3563    },
     3564
     3565    require: function(type, src, cb) {
    34973566        const element = document.createElement(type === `css` ? `link` : `script`);
    34983567        switch (type) {
    3499             case `css`:
    3500                 element.type = `text/css`;
    3501                 element.href = src;
    3502                 element.rel = `stylesheet`;
    3503                 break;
    3504             case `js`:
    3505                 element.type = `text/javascript`;
    3506                 element.src = src;
    3507                 break;
    3508             default:
    3509                 return;
     3568        case `css`:
     3569            element.type = `text/css`;
     3570            element.href = src;
     3571            element.rel = `stylesheet`;
     3572            break;
     3573        case `js`:
     3574            element.type = `text/javascript`;
     3575            element.src = src;
     3576            break;
     3577        default:
     3578            return;
    35103579        }
    35113580        element.onload = function () {
     
    35243593        const script = program.getValue(command.script);
    35253594        const imports = command.imports;
     3595        imports.caller = program.script;
    35263596        const moduleRecord = command.module ? program.getSymbolRecord(command.module) : null;
    35273597        try {
    35283598            EasyCoder.tokeniseAndCompile(script.split(`\n`), imports, moduleRecord, this, command.then);
    35293599        } catch (err) {
    3530             this.reportError(err, EasyCoder.program, program.source);
     3600            EasyCoder.reportError(err, program, program.source);
    35313601            if (program.onError) {
    35323602                program.run(program.onError);
    3533             } else if (program.parent && program.parent.onError) {
    3534                 program.parent.run(program.parent.onError);
     3603            } else {
     3604                let parent = program.parent;
     3605                if (parent && parent.onError) {
     3606                    parent.run(parent.onError);
     3607                }
    35353608            }
    35363609            return;
    35373610        }
    35383611        if (command.nowait) {
    3539             this.run(program.nextPc);
     3612            EasyCoder.run(program.nextPc);
    35403613        }
    35413614    },
     
    35493622        this.compiling = true;
    35503623        const compiler = EasyCoder_Compiler;
     3624        this.compiler = compiler;
    35513625        compiler.value = EasyCoder_Value;
    35523626        compiler.condition = EasyCoder_Condition;
    3553         compiler.domain = EasyCoder.domain;
     3627        compiler.domain = this.domain;
    35543628        compiler.imports = imports;
    35553629        const program = EasyCoder_Compiler.compile(tokens);
     
    35573631        this.compiling = false;
    35583632
    3559         program.EasyCoder = EasyCoder;
     3633        program.EasyCoder = this;
    35603634        program.value = EasyCoder_Value;
    35613635        program.condition = EasyCoder_Condition;
     
    35983672    },
    35993673
    3600     tokeniseFile: file => {
     3674    tokeniseFile: function(file) {
    36013675        const scriptLines = [];
    36023676        const tokens = [];
     
    36493723            }
    36503724        });
    3651         return { scriptLines, tokens };
     3725        return {scriptLines, tokens};
    36523726    },
    36533727
     
    36563730        let program = null;
    36573731        const startCompile = Date.now();
    3658         const source = EasyCoder.tokeniseFile(file);
     3732        const source = this.tokeniseFile(file);
    36593733        try {
    3660             program = EasyCoder.compileScript(source, imports, module, parent);
    3661             const name = program.script ? program.script : `<anon>`;
     3734            program = this.compileScript(source, imports, module, parent);
     3735            this.scriptIndex++;
     3736            if (!program.script) {
     3737                program.script = this.scriptIndex;
     3738            }
    36623739            const finishCompile = Date.now();
    3663             console.log(`${finishCompile - EasyCoder.timestamp} ms: ` + `Compiled ${name}: ${source.scriptLines.length} lines (${source.tokens.length} tokens) in ` + `${finishCompile - startCompile} ms`);
     3740            console.log(`${finishCompile - this.timestamp} ms: ` +
     3741                `Compiled ${program.script}: ${source.scriptLines.length} lines (${source.tokens.length} tokens) in ` +
     3742                `${finishCompile - startCompile} ms`);
    36643743        } catch (err) {
    36653744            if (err.message !== `stop`) {
    3666                 const p = EasyCoder.program;
    3667                 this.reportError(err, p, source);
    3668                 if (p.onError) {
    3669                     p.run(p.onError);
     3745                this.reportError(err, parent, source);
     3746                if (parent && parent.onError) {
     3747                    parent.run(parent.onError);
    36703748                }
    36713749            }
     
    36783756    },
    36793757
    3680     tokenise: source => {
     3758    tokenise: function(source) {
    36813759        const script = source.split(`\n`);
    3682         if (!_this.tokenising) {
     3760        if (!this.tokenising) {
    36833761            try {
    3684                 EasyCoder.tokeniseAndCompile(script);
     3762                this.tokeniseAndCompile(script);
    36853763            } catch (err) {
    3686                 EasyCoder.reportError(err, null, source);
    3687             }
    3688             _this.tokenising = true;
    3689         }
    3690     },
    3691 
    3692     setPluginCount: count => {
    3693         _this.plugins = [];
    3694         _this.pluginCount = count;
    3695     },
    3696 
    3697     checkPlugin: name => {
     3764                this.reportError(err, null, source);
     3765            }
     3766            this.tokenising = true;
     3767        }
     3768    },
     3769
     3770    setPluginCount: function(count) {
     3771        EasyCoder.plugins = [];
     3772        EasyCoder.pluginCount = count;
     3773    },
     3774
     3775    checkPlugin: function(name) {
    36983776        return EasyCoder.domain[name];
    36993777    },
    37003778
    3701     getPlugin: (name, src, onload) => {
     3779    getPlugin: function(name, src, onload) {
    37023780        if (EasyCoder.domain[name]) {
    37033781            onload();
     
    37143792    },
    37153793
    3716     addGlobalPlugin: (name, handler) => {
    3717         _this.plugins.push({
     3794    addGlobalPlugin: function(name, handler) {
     3795        // alert(`Add plugin ${name}`);
     3796        EasyCoder.plugins.push({
    37183797            name,
    37193798            handler
    37203799        });
    3721         if (_this.plugins.length === _this.pluginCount) {
    3722             _this.plugins.forEach(function (plugin) {
     3800        if (EasyCoder.plugins.length === EasyCoder.pluginCount) {
     3801            EasyCoder.plugins.forEach(function (plugin) {
    37233802                EasyCoder.domain[plugin.name] = plugin.handler;
    37243803            });
    3725             EasyCoder.tokenise(_this.source);
    3726         }
    3727     },
    3728 
    3729     addLocalPlugin: (name, handler, callback) => {
     3804            EasyCoder.tokenise(EasyCoder.source);
     3805        }
     3806    },
     3807
     3808    addLocalPlugin: function(name, handler, callback) {
    37303809        EasyCoder.domain[name] = handler;
    37313810        callback();
    37323811    },
    37333812
    3734     getPluginsPath: () => {
     3813    getPluginsPath: function() {
    37353814        return EasyCoder.pluginsPath;
    37363815    },
    37373816
    3738     loadPluginJs: path => {
    3739         console.log(`${Date.now() - EasyCoder.timestamp} ms: Load ${path}/easycoder/plugins.js`);
     3817    loadPluginJs: function(path) {
     3818        console.log(`${Date.now() - this.timestamp} ms: Load ${path}/easycoder/plugins.js`);
    37403819        const script = document.createElement(`script`);
    3741         script.src = `${window.location.origin}${path}/easycoder/plugins.js?ver=${EasyCoder.version}`;
     3820        script.src = `${window.location.origin}${path}/easycoder/plugins.js?ver=${this.version}`;
    37423821        script.type = `text/javascript`;
    3743         script.onload = function () {
    3744             EasyCoder_Plugins.getGlobalPlugins(EasyCoder.timestamp, path, EasyCoder.setPluginCount, EasyCoder.getPlugin, EasyCoder.addGlobalPlugin);
     3822        script.onload = () => {
     3823            EasyCoder_Plugins.getGlobalPlugins(
     3824                this.timestamp,
     3825                path,
     3826                this.setPluginCount,
     3827                this.getPlugin,
     3828                this.addGlobalPlugin
     3829            );
    37453830        };
    37463831        script.onerror = () => {
    37473832            if (path) {
    3748                 EasyCoder.loadPluginJs(path.slice(0, path.lastIndexOf(`/`)));
     3833                this.loadPluginJs(path.slice(0, path.lastIndexOf(`/`)));
    37493834            } else {
    3750                 EasyCoder.reportError({
     3835                this.reportError({
    37513836                    message: `Can't load plugins.js`
    3752                 }, EasyCoder.program, _this.source);
     3837                }, this.program, this.source);
    37533838            }
    37543839        };
    37553840        document.head.appendChild(script);
    3756         EasyCoder.pluginsPath = path;
    3757     },
    3758 
    3759     start: source => {
    3760         _this.source = source;
     3841        this.pluginsPath = path;
     3842    },
     3843
     3844    start: function(source) {
     3845        this.source = source;
     3846        this.scriptIndex = 0;
    37613847        let pathname = window.location.pathname;
    37623848        if (pathname.endsWith(`/`)) {
     
    37663852        }
    37673853        if (typeof EasyCoder_Plugins === `undefined`) {
    3768             EasyCoder.loadPluginJs(pathname);
     3854            this.loadPluginJs(pathname);
    37693855        } else {
    3770             EasyCoder.pluginsPath = pathname;
    3771             EasyCoder_Plugins.getGlobalPlugins(EasyCoder.timestamp, pathname, EasyCoder.setPluginCount, EasyCoder.getPlugin, EasyCoder.addGlobalPlugin);
     3856            this.pluginsPath = pathname;
     3857            EasyCoder_Plugins.getGlobalPlugins(
     3858                this.timestamp,
     3859                pathname,
     3860                this.setPluginCount,
     3861                this.getPlugin,
     3862                this.addGlobalPlugin
     3863            );
    37723864        }
    37733865    }
    37743866};
    3775 
    3776 module.exports = EasyCoder;
    3777 },{"./Compare":2,"./Compile":3,"./Condition":4,"./Core":5,"./Run":7,"./Value":8}],7:[function(require,module,exports){
    37783867const EasyCoder_Run = {
    37793868
    3780     run: (program, pc) => {
     3869    name: `EasyCoder_Run`,
     3870
     3871    run: (program, pc) =>{
    37813872
    37823873        const queue = [];
    37833874
    3784         const minIndent = scriptLines => {
     3875        const minIndent = (scriptLines) => {
    37853876            let count = 9999;
    37863877            scriptLines.forEach(function (element) {
     
    38123903                if (program.watchdog > 1000000) {
    38133904                    program.lino = program[program.pc].lino;
    3814                     program.reportError(new Error(`Program runaway intercepted.\nHave you forgotten to increment a loop counter?`, program), program);
     3905                    program.reportError(
     3906                        new Error(`Program runaway intercepted.\nHave you forgotten to increment a loop counter?`, program),
     3907                        program);
    38153908                    break;
    38163909                }
     
    38693962                                }
    38703963                                switch (program.tracer.alignment) {
    3871                                     case `horizontal`:
    3872                                         if (index < array.length - 1) {
    3873                                             variables += `, `;
    3874                                         }
    3875                                         break;
    3876                                     case `vertical`:
    3877                                         variables += `<br>`;
    3878                                         break;
     3964                                case `horizontal`:
     3965                                    if (index < array.length - 1) {
     3966                                        variables += `, `;
     3967                                    }
     3968                                    break;
     3969                                case `vertical`:
     3970                                    variables += `<br>`;
     3971                                    break;
    38793972                                }
    38803973                            });
     
    38843977                                if (command.lino) {
    38853978                                    const text = scriptLines[command.lino - n].line.substr(minSpace);
    3886                                     trace += `<input type="text" name="${n}"` + `value="${command.lino - n + 1}: ${text.split(`\\s`).join(` `)}"` + `style="width:100%;border:none;enabled:false">`;
     3979                                    trace += `<input type="text" name="${n}"` +
     3980                  `value="${command.lino - n + 1}: ${text.split(`\\s`).join(` `)}"` +
     3981                  `style="width:100%;border:none;enabled:false">`;
    38873982                                }
    38883983                                trace += `<br>`;
     
    39324027    },
    39334028
    3934     exit: program => {
     4029    exit: (program) => {
    39354030        if (program.onExit) {
     4031            delete EasyCoder.scripts[program.script];
    39364032            program.parent.run(program.onExit);
    39374033            program.module.program = null;
     
    39414037    }
    39424038};
    3943 
    3944 module.exports = EasyCoder_Run;
    3945 },{}],8:[function(require,module,exports){
    39464039const EasyCoder_Value = {
    39474040
    3948     getItem: compiler => {
     4041    name: `EasyCoder_Value`,
     4042
     4043    getItem: (compiler) => {
    39494044        const token = compiler.getToken();
    39504045        if (!token) {
     
    40434138        const type = value.type;
    40444139        switch (type) {
    4045             case `cat`:
    4046                 return {
    4047                     type: `constant`,
    4048                     numeric: false,
    4049                     content: value.parts.reduce(function (acc, part) {
    4050                         return acc + EasyCoder_Value.doValue(program, part).content;
    4051                     }, ``)
    4052                 };
    4053             case `boolean`:
    4054             case `constant`:
    4055                 return value;
    4056             case `symbol`:
    4057                 const symbol = program.getSymbolRecord(value.name);
    4058                 if (symbol.isValueHolder) {
    4059                     const symbolValue = symbol.value[symbol.index];
    4060                     if (symbolValue) {
    4061                         const v = symbolValue.content;
    4062                         if (v === null || typeof v === `undefined`) {
    4063                             symbolValue.content = symbolValue.numeric ? 0 : ``;
    4064                         }
    4065                         return symbolValue;
    4066                     } else {
    4067                         return null;
    4068                     }
     4140        case `cat`:
     4141            return {
     4142                type: `constant`,
     4143                numeric: false,
     4144                content: value.parts.reduce(function (acc, part) {
     4145                    return acc + EasyCoder_Value.doValue(program, part).content;
     4146                }, ``)
     4147            };
     4148        case `boolean`:
     4149        case `constant`:
     4150            return value;
     4151        case `symbol`:
     4152            const symbol = program.getSymbolRecord(value.name);
     4153            if (symbol.isValueHolder) {
     4154                const symbolValue = symbol.value[symbol.index];
     4155                if (symbolValue) {
     4156                    const v = symbolValue.content;
     4157                    if (v === null || typeof v === `undefined`) {
     4158                        symbolValue.content = symbolValue.numeric ? 0 : ``;
     4159                    }
     4160                    return symbolValue;
    40694161                } else {
    4070                     const handler = program.domain[symbol.domain].value;
    4071                     return handler.get(program, value);
    4072                 }
    4073             default:
    4074                 break;
     4162                    return null;
     4163                }
     4164            } else {
     4165                const handler = program.domain[symbol.domain].value;
     4166                return handler.get(program, value);
     4167            }
     4168        default:
     4169            break;
    40754170        }
    40764171        // Call the given domain to handle a value
     
    41114206        if (value) {
    41124207            switch (encoding) {
    4113                 case `ec`:
    4114                     return value.replace(/'/g, `~sq~`).replace(/"/g, `~dq~`).replace(/\n/g, `%0a`).replace(/\r/g, `%0d`);
    4115                 case `url`:
    4116                     return encodeURIComponent(value.replace(/\s/g, `+`));
    4117                 case `sanitize`:
    4118                     return value.normalize(`NFD`).replace(/[\u0300-\u036f]/g, ``);
     4208            case `ec`:
     4209                return value.replace(/'/g, `~sq~`)
     4210                    .replace(/"/g, `~dq~`)
     4211                    .replace(/\n/g, `%0a`)
     4212                    .replace(/\r/g, `%0d`);
     4213            case `url`:
     4214                return encodeURIComponent(value.replace(/\s/g, `+`));
     4215            case `sanitize`:
     4216                return value.normalize(`NFD`).replace(/[\u0300-\u036f]/g, ``);
    41194217            }
    41204218        }
     
    41254223        if (value) {
    41264224            switch (encoding) {
    4127                 case `ec`:
    4128                     return value.replace(/~dq~/g, `"`).replace(/~sq~/g, `'`).replace(/%0a/g, `\n`).replace(/%0d/g, `\r`);
    4129                 case `url`:
    4130                     const decoded = decodeURIComponent(value);
    4131                     return decoded.replace(/\+/g, ` `);
     4225            case `ec`:
     4226                return value.replace(/~dq~/g, `"`)
     4227                    .replace(/~sq~/g, `'`)
     4228                    .replace(/%0a/g, `\n`)
     4229                    .replace(/%0d/g, `\r`);
     4230            case `url`:
     4231                const decoded = decodeURIComponent(value);
     4232                return decoded.replace(/\+/g, ` `);
    41324233            }
    41334234        }
     
    41354236    }
    41364237};
    4137 
    4138 module.exports = EasyCoder_Value;
    4139 },{}]},{},[1]);
     4238EasyCoder.version = `2.5.2`;
     4239EasyCoder.timestamp = Date.now();
     4240console.log(`EasyCoder loaded; waiting for page`);
     4241
     4242function EasyCoder_Startup() {
     4243    console.log(`${Date.now() - EasyCoder.timestamp} ms: Page loaded; reset timer & start EasyCoder`);
     4244    EasyCoder.timestamp = Date.now();
     4245    EasyCoder.scripts = {};
     4246    window.EasyCoder = EasyCoder;
     4247    const script = document.getElementById(`easycoder-script`);
     4248    if (script) {
     4249        script.style.display = `none`;
     4250        try {
     4251            EasyCoder.start(script.innerText);
     4252        }
     4253        catch (err) {
     4254            EasyCoder.reportError(err);
     4255        }
     4256    }
     4257}
     4258
     4259// For browsers
     4260window.onload = EasyCoder_Startup;
  • easycoder/trunk/easycoder.php

    r2168730 r2208785  
    44  * Plugin URI: https://easycoder.software
    55  * Description: Control the appearance and behavior of your posts and pages by embedding simple English-like scripts, without the need to learn JavaScript.
    6   * Version: 2.5.2
     6  * Version: 2.5.3
    77  * Author: EasyCoder Software
    88  * Author URI: https://easycoder.software
     
    1717  function easycoder_enqueue_script() {   
    1818    wp_enqueue_script('easycoder_script', plugin_dir_url( __FILE__ )
    19             . 'easycoder-min.js', array(), '2.5.2');
     19            . 'easycoder-min.js', array(), '2.5.3');
    2020  }
    2121 
  • easycoder/trunk/plugins/anagrams.js

    r2084464 r2208785  
    11// eslint-disable-next-line no-unused-vars
    22const EasyCoder_Anagrams = {
     3
     4    name: `EasyCoder_Anagrams`,
    35
    46    value: {
  • easycoder/trunk/plugins/aws.js

    r2102119 r2208785  
    11const EasyCoder_AWS = {
     2
     3    name: `EasyCoder_AWS`,
    24
    35    AWS: {
  • easycoder/trunk/plugins/browser.js

    r2168730 r2208785  
    11const EasyCoder_Browser = {
     2
     3    name: `EasyCoder_Browser`,
    24
    35    A: {
     
    356358                        const imports = compiler.imports;
    357359                        if (imports && imports.length > 0) {
    358                             const parent = imports[0].name;
     360                            // This section is used by Codex to force run in Run panel, which must be the first import
    359361                            compiler.addCommand({
    360362                                domain: `browser`,
     
    362364                                lino,
    363365                                name: symbolRecord.name,
    364                                 parent,
     366                                parent: imports[0],
    365367                                imported: true
    366368                            });
     
    402404                }
    403405                targetRecord.element[targetRecord.index] = document.createElement(targetRecord.keyword);
    404                 if (!this.elementId) {
    405                     this.elementId = 0;
    406                 }
    407                 targetRecord.element[targetRecord.index].id = `ec-${targetRecord.name}-${targetRecord.index}-${this.elementId++}`;
     406                if (!program.elementId) {
     407                    program.elementId = 0;
     408                }
     409                targetRecord.element[targetRecord.index].id =
     410                    `ec-${targetRecord.name}-${targetRecord.index}-${program.elementId++}`;
    408411                if (targetRecord.keyword === `a`) {
    409412                    targetRecord.element[targetRecord.index].setAttribute(`href`, `#`);
     
    15451548
    15461549        compile: (compiler) => {
     1550            const lino = compiler.getLino();
    15471551            let name = null;
    15481552            if (compiler.nextIsSymbol()) {
     
    15561560                    domain: `browser`,
    15571561                    keyword: `scroll`,
     1562                    lino,
    15581563                    name,
    15591564                    to
     
    16831688                            }
    16841689                        }
    1685                         throw new Error(`Expected a symbol at '{compiler.getToken()}'`);
     1690                        throw new Error(`'${compiler.getToken()}' is not a symbol`);
    16861691                    }
    16871692                } else if (token === `id`) {
     
    25042509                        };
    25052510                    }
    2506                     throw new Error(`Expected a symbol at '{compiler.getToken()}'`);
     2511                    throw new Error(`'${compiler.getToken()}' is not a symbol`);
    25072512                }
    25082513                return null;
  • easycoder/trunk/plugins/ckeditor.js

    r2038748 r2208785  
    11const EasyCoder_CKEditor = {
     2
     3    name: `EasyCoder_CKEditor`,
    24
    35    CKEditor: {
  • easycoder/trunk/plugins/codemirror.js

    r2102119 r2208785  
    11const EasyCoder_CodeMirror = {
     2
     3    name: `EasyCoder_CodeMirror`,
    24
    35    CodeMirror: {
     
    109111                break;
    110112            case `attach`:
    111                 editor = program.getSymbolRecord(command.editor);
    112                 const element = document.getElementById(editor.element[editor.index].id);
    113                 editor.editor = CodeMirror.fromTextArea(element, {
    114                     mode: command.mode,
    115                     theme: `default`,
    116                     lineNumbers: true
    117                 });
    118                 editor.editor.setSize(`100%`, `100%`);
     113                try {
     114                    editor = program.getSymbolRecord(command.editor);
     115                    const element = document.getElementById(editor.element[editor.index].id);
     116                    editor.editor = CodeMirror.fromTextArea(element, {
     117                        mode: command.mode,
     118                        theme: `default`,
     119                        lineNumbers: true
     120                    });
     121                    editor.editor.setSize(`100%`, `100%`);
     122                } catch (err) { alert(err); }
    119123                break;
    120124            case `setContent`:
  • easycoder/trunk/plugins/dummy.js

    r2052097 r2208785  
    11const EasyCoder_Dummy = {
     2
     3    name: `EasyCoder_Dummy`,
    24
    35    Dummy: {
  • easycoder/trunk/plugins/gmap.js

    r2136853 r2208785  
    11
    22const EasyCoder_GMap = {
     3
     4    name: `EasyCoder_GMap`,
    35
    46    Create: {
  • easycoder/trunk/plugins/json.js

    r2107932 r2208785  
    11const EasyCoder_Json = {
     2
     3    name: `EasyCoder_JSON`,
    24
    35    Json: {
     
    165167            case `split`:
    166168                item = compiler.getNextValue();
    167                 if (compiler.tokenIs(`into`)) {
     169                let on = `\n`;
     170                if (compiler.tokenIs(`on`)) {
     171                    on = compiler.getNextValue();
     172                }
     173                if ([`giving`, `into`].includes(compiler.getToken())) {
    168174                    if (compiler.nextIsSymbol()) {
    169175                        const targetRecord = compiler.getSymbolRecord();
     
    176182                                request,
    177183                                item,
     184                                on,
    178185                                target: targetRecord.name
    179186                            });
    180187                            return true;
     188                        }
     189                    }
     190                }
     191                break;
     192            case `replace`:
     193                if (compiler.nextTokenIs(`element`)) {
     194                    const index = compiler.getNextValue();
     195                    if (compiler.tokenIs(`of`)) {
     196                        if (compiler.nextIsSymbol()) {
     197                            const targetRecord = compiler.getSymbolRecord();
     198                            if (targetRecord.keyword === `variable`) {
     199                                if ([`by`, `with`].includes(compiler.nextToken())) {
     200                                    const value = compiler.getNextValue();
     201                                    compiler.addCommand({
     202                                        domain: `json`,
     203                                        keyword: `json`,
     204                                        lino,
     205                                        request,
     206                                        target: targetRecord.name,
     207                                        index,
     208                                        value
     209                                    });
     210                                    return true;
     211                                }
     212                            }
    181213                        }
    182214                    }
     
    237269                targetRecord = program.getSymbolRecord(command.target);
    238270                const list = program.getValue(targetRecord.value[targetRecord.index]);
    239                 content = list ? JSON.stringify(JSON.parse(list).sort()) : list;
     271                content = list ? JSON.stringify(JSON.parse(list).sort()) : null;
    240272                targetRecord.value[targetRecord.index] = {
    241273                    type: `constant`,
     
    327359                const existing = targetRecord.value[targetRecord.index].content;
    328360                record = existing ? JSON.parse(existing) : [];
    329                 record.push(content);
    330                 targetRecord.value[targetRecord.index].content = JSON.stringify(record);
     361                record.push((`[`, `{`).includes(content[0]) ? JSON.parse(content) :content);
     362                targetRecord.value[targetRecord.index] = {
     363                    type: `constant`,
     364                    numeric: false,
     365                    content: JSON.stringify(record)
     366                };
    331367                break;
    332368            case `split`:
    333369                content = program.getValue(command.item);
    334                 targetRecord = program.getSymbolRecord(command.target);
    335                 targetRecord.value[targetRecord.index].content = content.split(`\n`);
     370                const on = program.getValue(command.on);
     371                targetRecord = program.getSymbolRecord(command.target);
     372                targetRecord.value[targetRecord.index] = {
     373                    type: `constant`,
     374                    numeric: false,
     375                    content: JSON.stringify(content.split(on))
     376                };
     377                break;
     378            case `replace`:
     379                targetRecord = program.getSymbolRecord(command.target);
     380                const index = program.getValue(command.index);
     381                const value = program.getValue(command.value);
     382                const current = targetRecord.value[targetRecord.index].content;
     383                record = current ? JSON.parse(current) : [];
     384                if (index > record.length - 1) {
     385                    program.runtimeError(command.lino, `Index out of range`);
     386                }
     387                record[index] = value;
     388                targetRecord.value[targetRecord.index].content = JSON.stringify(record);
    336389                break;
    337390            }
  • easycoder/trunk/plugins/rest.js

    r2168730 r2208785  
    11const EasyCoder_Rest = {
     2
     3    name: `EasyCoder_Rest`,
    24
    35    Rest: {
     
    111113            const rest = EasyCoder_Plugins.rest();
    112114            const path = url.startsWith(`http`) ? url
    113                 : `${window.location.origin}${rest ? `/${rest}` : ``}/${url}`;
     115                : url[0] === `/` ? url.substr(1)
     116                    : `${window.location.origin}${rest ? `/${rest}` : ``}/${url}`;
    114117
    115118            const request = EasyCoder_Rest.Rest.createCORSRequest(command.request, path);
     
    121124
    122125            request.onload = function () {
    123                 var content = request.responseText;
    124                 if (content.length > 0 && ![`[`, `{`].includes(content.charAt(0))) {
    125                     // content = program.decode(content);
    126                 }
    127                 if (command.target) {
    128                     const targetRecord = program.getSymbolRecord(command.target);
    129                     targetRecord.value[targetRecord.index] = {
    130                         type: `constant`,
    131                         numeric: false,
    132                         content
    133                     };
     126                if (200 <= request.status && request.status < 400) {
     127                    var content = request.responseText.trim();
     128                    if (command.target) {
     129                        const targetRecord = program.getSymbolRecord(command.target);
     130                        targetRecord.value[targetRecord.index] = {
     131                            type: `constant`,
     132                            numeric: false,
     133                            content
     134                        };
     135                        targetRecord.used = true;
     136                    }
     137                } else {
     138                    const error = `${request.status} ${request.statusText}`;
     139                    if (command.onError) {
     140                        program.errorMessage = `Exception trapped: ${error}`;
     141                        program.run(command.onError);
     142                    } else {
     143                        program.runtimeError(command.lino, `Error: ${error}`);
     144                    }
    134145                }
    135146                program.run(command.pc + 1);
     
    148159            switch (command.request) {
    149160            case `get`:
     161                // alert(`GET from ${path}`);
    150162                // console.log(`GET from ${path}`);
    151163                // request.open(`GET`, path);
     
    156168                console.log(`POST to ${path}`);
    157169                // request.open(`POST`, path);
    158                 if (value.charAt(0) === `{` || !isNaN(value)) {
     170                if (value.length >0 && value.charAt(0) === `{`) {
    159171                    request.setRequestHeader(`Content-Type`, `application/json; charset=UTF-8`);
    160172                    //            console.log(`value=${value}`);
  • easycoder/trunk/plugins/showdown.js

    r2084464 r2208785  
    11const EasyCoder_Showdown = {
     2
     3    name: `EasyCoder_Showdown`,
    24
    35    Load: {
     
    2224                program.require(`js`, `https://cdn.rawgit.com/showdownjs/showdown/1.9.0/dist/showdown.min.js`, function () {
    2325                    this.showdown_loaded = true;
    24                     showdown.extension(`Extension`, {
    25                         type: `lang`,
    26                         filter: function (text, converter) {
    27                             const callback = program.getSymbolRecord(converter.callback);
    28                             return text.replace(/~([^~]+)~/g, function (match, group) {
    29                                 callback.payload = group;
    30                                 program.run(callback.cb);
    31                                 return callback.payload;
    32                             });
    33                         }
    34                     });
     26                    EasyCoder_Showdown.setupExtension();
    3527                    program.run(command.pc + 1);
    3628                });
    3729            }
    3830            else {
     31                EasyCoder_Showdown.setupExtension();
    3932                return command.pc + 1;
    4033            }
    4134            return 0;
    4235        }
     36    },
     37
     38    setupExtension: () => {
     39        showdown.extension(`Extension`, {
     40            type: `lang`,
     41            filter: function (text, converter) {
     42                const callback = program.getSymbolRecord(converter.callback);
     43                return text.replace(/~([^~]+)~/g, function (match, group) {
     44                    callback.payload = group;
     45                    program.run(callback.cb);
     46                    return callback.payload;
     47                });
     48            }
     49        });
    4350    },
    4451
  • easycoder/trunk/plugins/svg.js

    r2102119 r2208785  
    11const EasyCoder_SVG = {
     2
     3    name: `EasyCoder_SVG`,
    24
    35    Circle: {
  • easycoder/trunk/plugins/ui.js

    r2052097 r2208785  
    11const EasyCoder_UI = {
     2
     3    name: `EasyCoder_UI`,
    24
    35    monthNames: [
  • easycoder/trunk/plugins/wof.js

    r2168730 r2208785  
    11// eslint-disable-next-line no-unused-vars
    22const EasyCoder_WOF = {
     3
     4    name: `EasyCoder_WOF`,
    35
    46    /*
  • easycoder/trunk/readme.txt

    r2168730 r2208785  
    2525* Draw and animate simple graphics
    2626* Create a Google Map, put markers on it and intearct with the map and the markers
     27* Use CodeMirror to create a unique color-coded text editor
    2728* Include the CKEditor rich text editor in your pages
    2829* Include the Showdown markdown converter in your pages
     
    3233*EasyCoder* scripts are embedded in your page or post, inside a special "preformatted" tag. When the page loads, *EasyCoder* looks for this element then compiles and runs the script it contains. When it interacts with HTML elements it attaches their IDs to its own variables, so your HTML and its controlling script are in the same file.
    3334
    34 The *EasyCoder* core module is currently about 55k bytes in its minimised form and it downloads its own plugin modules from a growing library. Its performance is good because it precompiles scripts - a process that takes only tens of milliseconds - and the compiled code for each command is only a thin wrapper around the corresponding JavaScript functionality.
     35The *EasyCoder* core module is currently about 58k bytes in its minimised form and it downloads its own plugin modules from a growing library. Its performance is good because it precompiles scripts - a process that takes only tens of milliseconds - and the compiled code for each command is only a thin wrapper around the corresponding JavaScript functionality.
    3536
    3637When *EasyCoder* detects an error, either in compilation or at runtime, it opens a popup window with a friendly error message that tries to tell you what went wrong and where in the script it happened.
     
    5354
    5455== Changelog ==
     56
     57= 2.5.3 09-dec-2019 =
     58* Revised run/import handling & minor additions
    5559
    5660= 2.5.2 05-oct-2019 =
Note: See TracChangeset for help on using the changeset viewer.