Plugin Directory

Changeset 2102119


Ignore:
Timestamp:
06/07/2019 09:27:33 AM (7 years ago)
Author:
gtanyware
Message:

Version 2.3.0; Bug fixes & support for learn-to-code

Location:
easycoder/trunk
Files:
1 added
1 deleted
11 edited

Legend:

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

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

    r2089142 r2102119  
    44const EasyCoder = require(`./easycoder/Main`);
    55
    6 EasyCoder.version = `2.3.0`;
     6EasyCoder.version = `2.3.1`;
    77EasyCoder.timestamp = Date.now();
    88console.log(`EasyCoder loaded; waiting for page`);
     
    9191    },
    9292
     93    more: () => {
     94        return _this.index < _this.tokens.length;
     95    },
     96
    9397    getToken: () => {
    9498        if (_this.index >= _this.tokens.length) {
     
    356360        EasyCoder_Compiler.addCommand({
    357361            domain: `core`,
    358             keyword: `stop`,
     362            keyword: `exit`,
    359363            lino: EasyCoder_Compiler.getLino(),
    360364            next: 0
     
    490494                    };
    491495                } else {
    492                     if (!value.numeric) {
     496                    if (!value.numeric && isNaN(value.content)) {
    493497                        program.nonNumericValueError(command.lino);
    494498                    }
    495                     const result = value.content + program.getValue(value1);
     499                    const result = parseInt(value.content) + parseInt(program.getValue(value1));
    496500                    target.value[target.index] = {
    497501                        type: `constant`,
     
    576580        }
    577581    },
     582
    578583    Clear: {
    579584
     
    665670                    keyword: `debug`,
    666671                    lino,
    667                     item: -1
     672                    item: `program`
    668673                });
    669674                return true;
     
    718723                    program.debugStep = true;
    719724                    break;
     725                case `program`:
     726                    console.log(`Debug program: ${JSON.stringify(program, null, 2)}`);
     727                    break;
    720728                default:
    721729                    if (item.content >= 0) {
    722730                        console.log(`Debug item ${item.content}: ${JSON.stringify(program[item.content], null, 2)}`);
    723                     } else {
    724                         console.log(`Debug program: ${JSON.stringify(program, null, 2)}`);
    725731                    }
    726732                    break;
     
    834840                    };
    835841                } else {
    836                     if (!value.numeric) {
     842                    if (!value.numeric && isNaN(value.content)) {
    837843                        program.nonNumericValueError(command, lino);
    838844                    }
    839                     const result = value.content / program.getValue(value2);
     845                    const result = parseInt(value.content) / parseInt(program.getValue(value2));
    840846                    target.value[target.index] = {
    841847                        type: `constant`,
     
    896902
    897903        run: () => {
     904            return 0;
     905        }
     906    },
     907
     908    Exit: {
     909
     910        compile: compiler => {
     911            compiler.next();
     912            compiler.addCommand({
     913                domain: `core`,
     914                keyword: `exit`
     915            });
     916            return true;
     917        },
     918
     919        run: program => {
     920            program.exit();
    898921            return 0;
    899922        }
     
    12401263                    };
    12411264                } else {
    1242                     if (!value.numeric) {
     1265                    if (!value.numeric && isNaN(value.content)) {
    12431266                        program.nonNumericValueError(command, lino);
    12441267                    }
    1245                     const result = value.content * program.getValue(value2);
     1268                    const result = parseInt(value.content) * parseInt(program.getValue(value2));
    12461269                    target.value[target.index] = {
    12471270                        type: `constant`,
     
    12981321            const action = compiler.nextToken();
    12991322            switch (action) {
    1300                 case `trigger`:
    13011323                case `close`:
    13021324                case `restore`:
     
    13311353            const cb = command.pc + 2;
    13321354            switch (command.action) {
    1333                 case `trigger`:
    1334                     program.onTrigger = cb;
    1335                     break;
    13361355                case `close`:
    13371356                    program.onClose = cb;
     
    13831402        compile: compiler => {
    13841403            const lino = compiler.getLino();
    1385             compiler.next();
    13861404            // Get the value
    1387             const value = compiler.getValue();
     1405            const value = compiler.getNextValue();
    13881406            if (compiler.tokenIs(`into`)) {
    1389                 compiler.next();
    1390                 if (compiler.isSymbol()) {
     1407                if (compiler.nextIsSymbol()) {
    13911408                    const target = compiler.getToken();
    13921409                    compiler.next();
     
    14441461                            });
    14451462                            return true;
     1463                        } else {
     1464                            throw new Error(`'${targetRecord.name}' does not hold a value`);
    14461465                        }
    14471466                    }
     
    15391558                }
    15401559            }
    1541             var module;
     1560            let module;
    15421561            if (compiler.tokenIs(`as`)) {
    15431562                if (compiler.nextIsSymbol(true)) {
     
    15501569                }
    15511570            }
     1571            let nowait = false;
     1572            if (compiler.tokenIs(`nowait`)) {
     1573                compiler.next();
     1574                nowait = true;
     1575            }
     1576            const pc = compiler.getPc();
    15521577            compiler.addCommand({
    15531578                domain: `core`,
     
    15561581                script,
    15571582                imports,
    1558                 module
     1583                module,
     1584                nowait,
     1585                then: 0
    15591586            });
     1587            // Get the 'then' code, if any
     1588            if (compiler.tokenIs(`then`)) {
     1589                const goto = compiler.getPc();
     1590                // Add a 'goto' to skip the 'then'
     1591                compiler.addCommand({
     1592                    domain: `core`,
     1593                    keyword: `goto`,
     1594                    goto: 0
     1595                });
     1596                // Fixup the link to the 'then' branch
     1597                compiler.getCommandAt(pc).then = compiler.getPc();
     1598                // Process the 'then' branch
     1599                compiler.next();
     1600                compiler.compileOne(true);
     1601                compiler.addCommand({
     1602                    domain: `core`,
     1603                    keyword: `stop`
     1604                });
     1605                // Fixup the 'goto'
     1606                compiler.getCommandAt(goto).goto = compiler.getPc();
     1607            }
    15601608            return true;
    15611609        },
     
    18331881                case `setReady`:
    18341882                    program.parent.run(program.parent.nextPc);
     1883                    program.parent.nextPc = 0;
    18351884                    break;
    18361885                case `setElements`:
     
    18691918                    const itemValue = program.evaluate(command.value);
    18701919                    if (itemValue) {
    1871                         if (itemValue.type === `boolean`) {
     1920                        if (itemValue.content instanceof Array) {
     1921                            targetJSON[itemName] = JSON.stringify(itemValue.content);
     1922                        } else if (itemValue.type === `boolean`) {
    18721923                            targetJSON[itemName] = itemValue.content;
    18731924                        } else {
     
    18961947            const lino = compiler.getLino();
    18971948            compiler.next();
     1949            if (compiler.more() && compiler.isSymbol()) {
     1950                const symbolRecord = compiler.getSymbolRecord();
     1951                if (symbolRecord.keyword === `module`) {
     1952                    compiler.next();
     1953                    compiler.addCommand({
     1954                        domain: `core`,
     1955                        keyword: `stop`,
     1956                        lino,
     1957                        name: symbolRecord.name
     1958                    });
     1959                    return true;
     1960                } else {
     1961                    return false;
     1962                }
     1963            }
    18981964            compiler.addCommand({
    18991965                domain: `core`,
     
    19051971        },
    19061972
    1907         run: () => {
    1908             return 0;
     1973        run: program => {
     1974            const command = program[program.pc];
     1975            if (command.name) {
     1976                const symbolRecord = program.getSymbolRecord(command.name);
     1977                symbolRecord.program.exit();
     1978            } else {
     1979                return 0;
     1980            }
     1981            return command.pc + 1;
    19091982        }
    19101983    },
     
    19922065                    };
    19932066                } else {
    1994                     if (!value.numeric) {
    1995                         program.nonNumericValueError(command, lino);
    1996                     }
    1997                     const result = program.getValue(value) - program.getValue(value1);
     2067                    if (!value.numeric && isNaN(value.content)) {
     2068                        program.nonNumericValueError(command.lino);
     2069                    }
     2070                    const result = parseInt(program.getValue(value)) - parseInt(program.getValue(value1));
    19982071                    target.value[target.index] = {
    19992072                        type: `constant`,
     
    21752248            case `end`:
    21762249                return EasyCoder_Core.End;
     2250            case `exit`:
     2251                return EasyCoder_Core.Exit;
    21772252            case `fork`:
    21782253                return EasyCoder_Core.Fork;
     
    23792454                };
    23802455            }
    2381             if (token === `encode`) {
     2456            if ([`encode`, `decode`, `lowercase`, `hash`].includes(token)) {
    23822457                compiler.next();
    23832458                const value = compiler.getValue();
    23842459                return {
    23852460                    domain: `core`,
    2386                     type: `encode`,
    2387                     value
    2388                 };
    2389             }
    2390             if (token === `decode`) {
    2391                 compiler.next();
    2392                 const value = compiler.getValue();
    2393                 return {
    2394                     domain: `core`,
    2395                     type: `decode`,
    2396                     value
    2397                 };
    2398             }
    2399             if (token === `lowercase`) {
    2400                 compiler.next();
    2401                 const value = compiler.getValue();
    2402                 return {
    2403                     domain: `core`,
    2404                     type: `lowercase`,
     2461                    type: token,
    24052462                    value
    24062463                };
     
    27402797                        content: program.getValue(value.value).toLowerCase()
    27412798                    };
     2799                case `hash`:
     2800                    const hashval = program.getValue(value.value);
     2801                    let hash = 0;
     2802                    if (hashval.length === 0) return hash;
     2803                    for (let i = 0; i < hashval.length; i++) {
     2804                        const chr = hashval.charCodeAt(i);
     2805                        hash = (hash << 5) - hash + chr;
     2806                        //                  hash |= 0; // Convert to 32bit integer
     2807                    }
     2808                    return {
     2809                        type: `constant`,
     2810                        numeric: true,
     2811                        content: hash
     2812                    };
    27422813                case `element`:
    27432814                    const element = program.getValue(value.element);
     
    27732844                    return {
    27742845                        type: `constant`,
    2775                         numeric: Number.isInteger(content),
     2846                        numeric: !isNaN(content),
    27762847                        content: typeof content === `object` ? JSON.stringify(content) : content
    27772848                    };
     
    28082879
    28092880        compile: compiler => {
     2881            if (compiler.isSymbol()) {
     2882                const symbolRecord = compiler.getSymbolRecord();
     2883                if (symbolRecord.keyword === `module`) {
     2884                    if (compiler.nextTokenIs(`is`)) {
     2885                        let sense = true;
     2886                        if (compiler.nextTokenIs(`not`)) {
     2887                            compiler.next();
     2888                            sense = false;
     2889                        }
     2890                        if (compiler.tokenIs(`running`)) {
     2891                            compiler.next();
     2892                            return {
     2893                                domain: `core`,
     2894                                type: `moduleRunning`,
     2895                                name: symbolRecord.name,
     2896                                sense
     2897                            };
     2898                        }
     2899                    }
     2900                    return null;
     2901                }
     2902            }
    28102903            if (compiler.tokenIs(`not`)) {
    2811                 compiler.next();
    2812                 const value = compiler.getValue();
     2904                const value = compiler.getNextValue();
    28132905                return {
    28142906                    domain: `core`,
     
    29052997                    return program.getValue(condition.value);
    29062998                case `numeric`:
    2907                     return Number.isInteger(program.getValue(condition.value1));
     2999                    return !isNaN(program.getValue(condition.value1));
    29083000                case `even`:
    29093001                    return program.getValue(condition.value1) % 2 === 0;
     
    29213013                case `not`:
    29223014                    return !program.getValue(condition.value);
     3015                case `moduleRunning`:
     3016                    const running = program.getSymbolRecord(condition.name).program;
     3017                    return condition.sense ? running : !running;
    29233018            }
    29243019            return false;
     
    29583053            message: `Line ${lino >= 0 ? lino : ``}: ${message}`
    29593054        }, EasyCoder.program);
     3055        program.aborted = true;
    29603056    },
    29613057    nonNumericValueError: function (lino) {
     
    30013097        console.log(errString);
    30023098        alert(errString);
    3003         EasyCoder.aborted = true;
    30043099    },
    30053100
     
    30653160        if (pc) {
    30663161            EasyCoder.program = this;
    3067             EasyCoder_Run(this, pc);
    3068         }
    3069     },
    3070 
    3071     trigger: function () {
    3072         if (this.onTrigger) {
    3073             EasyCoder_Run(this, this.onTrigger);
    3074         }
     3162            EasyCoder_Run.run(this, pc);
     3163        }
     3164    },
     3165
     3166    exit: function () {
     3167        EasyCoder_Run.exit(this);
    30753168    },
    30763169
     
    31093202        const script = program.getValue(command.script);
    31103203        const imports = command.imports;
    3111         const module = command.module ? program.getSymbolRecord(command.module) : null;
    3112         EasyCoder.tokeniseScript(script.split(`\n`), imports, module, this);
     3204        const moduleRecord = command.module ? program.getSymbolRecord(command.module) : null;
     3205        EasyCoder.tokeniseScript(script.split(`\n`), imports, moduleRecord, this, command.then);
     3206        if (command.nowait) {
     3207            this.run(program.nextPc);
     3208        }
    31133209    },
    31143210
     
    31383234        program.source = source;
    31393235        program.run = this.run;
     3236        program.exit = this.exit;
    31403237        program.runScript = this.runScript;
    31413238        program.evaluate = this.evaluate;
     
    31463243        program.decode = this.decode;
    31473244        program.domain = this.domain;
    3148         program.trigger = this.trigger;
    31493245        program.require = this.require;
    31503246        program.isUndefined = this.isUndefined;
     
    31733269    },
    31743270
    3175     tokeniseScript: function (file, imports, module, parent) {
     3271    tokeniseScript: function (file, imports, module, parent, then) {
    31763272        //  console.log('Tokenise script: ');
    31773273        let program = null;
     
    31893285        }
    31903286        this.setupTracer();
    3191         //    console.log('Run the script');
    31923287        if (program) {
    3193             //  console.log('Program: '+ JSON.stringify(program, null, 2));
    3194             EasyCoder_Run(program, 0);
     3288            program.onExit = then;
     3289            EasyCoder_Run.run(program, 0);
    31953290        }
    31963291    },
     
    32773372    start: source => {
    32783373        _this.source = source;
    3279         var pathname = window.location.pathname;
     3374        let pathname = window.location.pathname;
    32803375        if (pathname.endsWith(`/`)) {
    32813376            pathname = pathname.slice(0, -1);
     3377        } else {
     3378            pathname = ``;
    32823379        }
    32833380        EasyCoder.loadPluginJs(pathname);
     
    32873384module.exports = EasyCoder;
    32883385},{"./Compare":2,"./Compile":3,"./Condition":4,"./Core":5,"./Run":7,"./Tokenise":8,"./Value":9}],7:[function(require,module,exports){
    3289 const EasyCoder_Run = (program, pc) => {
    3290 
    3291     const queue = [];
    3292 
    3293     const minIndent = scriptLines => {
    3294         var count = 9999;
    3295         scriptLines.forEach(function (element) {
    3296             const item = element.line;
    3297             var n = 0;
    3298             while (n < item.length) {
    3299                 if (item[n] !== ` `) {
     3386const EasyCoder_Run = {
     3387
     3388    run: (program, pc) => {
     3389
     3390        const queue = [];
     3391
     3392        const minIndent = scriptLines => {
     3393            var count = 9999;
     3394            scriptLines.forEach(function (element) {
     3395                const item = element.line;
     3396                var n = 0;
     3397                while (n < item.length) {
     3398                    if (item[n] !== ` `) {
     3399                        break;
     3400                    }
     3401                    n++;
     3402                }
     3403                if (n > 0 && n < count) {
     3404                    count = n;
     3405                }
     3406            });
     3407            return 0;
     3408        };
     3409
     3410        if (queue.length) {
     3411            queue.push(pc);
     3412            return;
     3413        }
     3414        program.register(program);
     3415        queue.push(pc);
     3416        while (queue.length > 0) {
     3417            program.pc = queue.shift();
     3418            program.watchdog = 0;
     3419            while (true) {
     3420                if (program.watchdog > 1000000) {
     3421                    program.lino = program[program.pc].lino;
     3422                    program.reportError(new Error(`Program runaway intercepted.\nHave you forgotten to increment a loop counter?`, program), program);
    33003423                    break;
    33013424                }
    3302                 n++;
    3303             }
    3304             if (n > 0 && n < count) {
    3305                 count = n;
    3306             }
    3307         });
    3308         return 0;
    3309         //    return count;
    3310     };
    3311 
    3312     if (queue.length) {
    3313         queue.push(pc);
    3314         return;
    3315     }
    3316     program.register(program);
    3317     queue.push(pc);
    3318     while (queue.length > 0) {
    3319         if (EasyCoder.aborted) {
    3320             break;
    3321         }
    3322         program.pc = queue.shift();
    3323         program.watchdog = 0;
    3324         while (true) {
    3325             if (program.watchdog > 1000000) {
    3326                 program.lino = program[program.pc].lino;
    3327                 program.reportError(new Error(`Program runaway intercepted.\nHave you forgotten to increment a loop counter?`, program), program);
    3328                 break;
    3329             }
    3330             program.watchdog++;
    3331             const domain = program[program.pc].domain;
    3332             if (program.debugStep) {
    3333                 console.log(`${program.script} ${program.pc} ${domain}:${program[program.pc].keyword}`);
    3334                 //              console.log(`${program.script} ${program.pc} ${domain}:${program.source.scriptLines[program[program.pc].lino].line}`);
    3335             }
    3336             const handler = program.domain[domain];
    3337             if (!handler) {
    3338                 program.runtimeError(program[program.pc].lino, `Unknown domain '${domain}'`);
    3339                 break;
    3340             }
    3341             program.pc = handler.run(program);
    3342             if (!program.pc) {
    3343                 break;
    3344             }
    3345             if (program.stop) {
    3346                 program.tracing = false;
    3347                 return;
    3348             }
    3349             if (program.tracing) {
    3350                 const command = program[program.pc];
    3351                 const scriptLines = program.source.scriptLines;
    3352                 const minSpace = minIndent(scriptLines);
    3353                 const tracer = document.getElementById(`easycoder-tracer`);
    3354                 if (!tracer) {
    3355                     program.runtimeError(command.lino, `Element 'easycoder-tracer' was not found`);
    3356                     return;
    3357                 }
    3358                 tracer.style.display = `block`;
    3359                 tracer.style.visibility = `visible`;
    3360                 var variables = ``;
    3361                 if (program.tracer) {
    3362                     const content = document.getElementById(`easycoder-tracer-content`);
    3363                     if (content) {
    3364                         program.tracer.variables.forEach(function (name, index, array) {
    3365                             const symbol = program.getSymbolRecord(name);
    3366                             if (symbol.elements > 1) {
    3367                                 variables += `${name}: ${symbol.index}/${symbol.elements}: `;
    3368                                 for (var n = 0; n < symbol.elements; n++) {
    3369                                     const value = symbol.value[n];
     3425                program.watchdog++;
     3426                const domain = program[program.pc].domain;
     3427                if (program.debugStep) {
     3428                    console.log(`${program.script} ${program.pc} ${domain}:${program[program.pc].keyword}`);
     3429                }
     3430                const handler = program.domain[domain];
     3431                if (!handler) {
     3432                    program.runtimeError(program[program.pc].lino, `Unknown domain '${domain}'`);
     3433                    break;
     3434                }
     3435                program.pc = handler.run(program);
     3436                if (!program.pc) {
     3437                    break;
     3438                }
     3439                if (program.stop) {
     3440                    program.tracing = false;
     3441                    break;
     3442                }
     3443                if (program.tracing) {
     3444                    const command = program[program.pc];
     3445                    const scriptLines = program.source.scriptLines;
     3446                    const minSpace = minIndent(scriptLines);
     3447                    const tracer = document.getElementById(`easycoder-tracer`);
     3448                    if (!tracer) {
     3449                        program.runtimeError(command.lino, `Element 'easycoder-tracer' was not found`);
     3450                        return;
     3451                    }
     3452                    tracer.style.display = `block`;
     3453                    tracer.style.visibility = `visible`;
     3454                    var variables = ``;
     3455                    if (program.tracer) {
     3456                        const content = document.getElementById(`easycoder-tracer-content`);
     3457                        if (content) {
     3458                            program.tracer.variables.forEach(function (name, index, array) {
     3459                                const symbol = program.getSymbolRecord(name);
     3460                                if (symbol.elements > 1) {
     3461                                    variables += `${name}: ${symbol.index}/${symbol.elements}: `;
     3462                                    for (var n = 0; n < symbol.elements; n++) {
     3463                                        const value = symbol.value[n];
     3464                                        if (value) {
     3465                                            variables += `${value.content} `;
     3466                                        } else {
     3467                                            variables += `undefined `;
     3468                                        }
     3469                                    }
     3470                                } else {
     3471                                    const value = symbol.value[symbol.index];
    33703472                                    if (value) {
    3371                                         variables += `${value.content} `;
     3473                                        variables += `${name}: ${value.content}`;
    33723474                                    } else {
    3373                                         variables += `undefined `;
     3475                                        variables += `${name}: undefined`;
    33743476                                    }
    33753477                                }
    3376                             } else {
    3377                                 const value = symbol.value[symbol.index];
    3378                                 if (value) {
    3379                                     variables += `${name}: ${value.content}`;
    3380                                 } else {
    3381                                     variables += `${name}: undefined`;
     3478                                switch (program.tracer.alignment) {
     3479                                    case `horizontal`:
     3480                                        if (index < array.length - 1) {
     3481                                            variables += `, `;
     3482                                        }
     3483                                        break;
     3484                                    case `vertical`:
     3485                                        variables += `<br>`;
     3486                                        break;
    33823487                                }
     3488                            });
     3489                            variables += `<hr>`;
     3490                            var trace = ``;
     3491                            for (var n = 5; n > 0; n--) {
     3492                                if (command.lino) {
     3493                                    trace += `<input type="text" name="${n}"` + `value="${scriptLines[command.lino - n].line.substr(minSpace)}"` + `style="width:100%;border:none;enabled:false">`;
     3494                                }
     3495                                trace += `<br>`;
    33833496                            }
    3384                             switch (program.tracer.alignment) {
    3385                                 case `horizontal`:
    3386                                     if (index < array.length - 1) {
    3387                                         variables += `, `;
    3388                                     }
    3389                                     break;
    3390                                 case `vertical`:
    3391                                     variables += `<br>`;
    3392                                     break;
    3393                             }
    3394                         });
    3395                         variables += `<hr>`;
    3396                         var trace = ``;
    3397                         for (var n = 5; n > 0; n--) {
    3398                             if (command.lino) {
    3399                                 trace += `<input type="text" name="${n}"` + `value="${scriptLines[command.lino - n].line.substr(minSpace)}"` + `style="width:100%;border:none;enabled:false">`;
    3400                             }
    3401                             trace += `<br>`;
     3497                            content.innerHTML = `${variables} ${trace}`;
     3498                            content.style.display = `block`;
     3499                            const run = document.getElementById(`easycoder-run-button`);
     3500                            const step = document.getElementById(`easycoder-step-button`);
     3501
     3502                            run.onclick = function () {
     3503                                run.blur();
     3504                                program.tracing = false;
     3505                                const content = document.getElementById(`easycoder-tracer-content`);
     3506                                content.style.display = `none`;
     3507                                try {
     3508                                    EasyCoder_Run.run(program, program.resume);
     3509                                } catch (err) {
     3510                                    const message = `Error in run handler: ` + err.message;
     3511                                    console.log(message);
     3512                                    alert(message);
     3513                                }
     3514                            };
     3515
     3516                            step.onclick = function () {
     3517                                console.log(`step`);
     3518                                step.blur();
     3519                                program.tracing = true;
     3520                                const content = document.getElementById(`easycoder-tracer-content`);
     3521                                content.style.display = `block`;
     3522                                try {
     3523                                    program.run(program.resume);
     3524                                } catch (err) {
     3525                                    const message = `Error in step handler: ` + err.message;
     3526                                    console.log(message);
     3527                                    alert(message);
     3528                                }
     3529                            };
    34023530                        }
    3403                         content.innerHTML = `${variables} ${trace}`;
    3404                         content.style.display = `block`;
    3405                         const run = document.getElementById(`easycoder-run-button`);
    3406                         const step = document.getElementById(`easycoder-step-button`);
    3407 
    3408                         run.onclick = function () {
    3409                             run.blur();
    3410                             program.tracing = false;
    3411                             const content = document.getElementById(`easycoder-tracer-content`);
    3412                             content.style.display = `none`;
    3413                             try {
    3414                                 EasyCoder_Run(program, program.resume);
    3415                             } catch (err) {
    3416                                 const message = `Error in run handler: ` + err.message;
    3417                                 console.log(message);
    3418                                 alert(message);
    3419                             }
    3420                         };
    3421 
    3422                         step.onclick = function () {
    3423                             console.log(`step`);
    3424                             step.blur();
    3425                             program.tracing = true;
    3426                             const content = document.getElementById(`easycoder-tracer-content`);
    3427                             content.style.display = `block`;
    3428                             try {
    3429                                 EasyCoder_Run(program, program.resume);
    3430                             } catch (err) {
    3431                                 const message = `Error in step handler: ` + err.message;
    3432                                 console.log(message);
    3433                                 alert(message);
    3434                             }
    3435                         };
    3436                     }
    3437 
    3438                     program.resume = program.pc;
    3439                     program.pc = 0;
    3440                 }
    3441                 break;
    3442             }
     3531
     3532                        program.resume = program.pc;
     3533                        program.pc = 0;
     3534                    }
     3535                    break;
     3536                }
     3537            }
     3538        }
     3539    },
     3540
     3541    exit: program => {
     3542        if (program.onExit) {
     3543            program.parent.run(program.onExit);
     3544            program.module.program = null;
     3545            program = null;
    34433546        }
    34443547    }
  • easycoder/trunk/easycoder.php

    r2089142 r2102119  
    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.3.0
     6  * Version: 2.3.1
    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.2.6');
     19            . 'easycoder-min.js', array(), '2.3.1');
    2020  }
    2121 
  • easycoder/trunk/plugins-sample.js

    r2089142 r2102119  
    9999            break;
    100100        }
     101    },
     102 
     103    rest: () => {
     104        return `wp-content/plugins/easycoder/rest.php`;
    101105    }
    102106};
  • easycoder/trunk/plugins/browser.js

    r2086338 r2102119  
    4545                const symbol = compiler.getSymbolRecord();
    4646                switch (symbol.keyword) {
    47                     case `a`:
    48                     case `blockquote`:
    49                     case `button`:
    50                     case `div`:
    51                     case `fieldset`:
    52                     case `file`:
    53                     case `form`:
    54                     case `h1`:
    55                     case `h2`:
    56                     case `h3`:
    57                     case `h4`:
    58                     case `h5`:
    59                     case `h6`:
    60                     case `img`:
    61                     case `input`:
    62                     case `label`:
    63                     case `legend`:
    64                     case `li`:
    65                     case `p`:
    66                     case `pre`:
    67                     case `select`:
    68                     case `span`:
    69                     case `table`:
    70                     case `td`:
    71                     case `text`:
    72                     case `textarea`:
    73                     case `tr`:
    74                     case `ul`:
    75                         symbol.used = true;
    76                         compiler.next();
    77                         if (compiler.tokenIs(`to`)) {
    78                             const cssId = compiler.getNextValue();
    79                             compiler.addCommand({
    80                                 domain: `browser`,
    81                                 keyword: `attach`,
    82                                 lino,
    83                                 type: symbol.keyword,
    84                                 symbol: symbol.name,
    85                                 cssId
    86                             });
    87                             return true;
    88                         }
    89                         break;
    90                     default:
    91                         compiler.addWarning(`type '${symbol.keyword}' not recognized in browser 'attach'`);
    92                         return false;
     47                case `a`:
     48                case `blockquote`:
     49                case `button`:
     50                case `div`:
     51                case `fieldset`:
     52                case `file`:
     53                case `form`:
     54                case `h1`:
     55                case `h2`:
     56                case `h3`:
     57                case `h4`:
     58                case `h5`:
     59                case `h6`:
     60                case `image`:
     61                case `img`:
     62                case `input`:
     63                case `label`:
     64                case `legend`:
     65                case `li`:
     66                case `p`:
     67                case `pre`:
     68                case `select`:
     69                case `span`:
     70                case `table`:
     71                case `td`:
     72                case `text`:
     73                case `textarea`:
     74                case `tr`:
     75                case `ul`:
     76                    symbol.used = true;
     77                    compiler.next();
     78                    if (compiler.tokenIs(`to`)) {
     79                        const cssId = compiler.getNextValue();
     80                        compiler.addCommand({
     81                            domain: `browser`,
     82                            keyword: `attach`,
     83                            lino,
     84                            type: symbol.keyword,
     85                            symbol: symbol.name,
     86                            cssId
     87                        });
     88                        return true;
     89                    }
     90                    break;
     91                default:
     92                    compiler.addWarning(`type '${symbol.keyword}' not recognized in browser 'attach'`);
     93                    return false;
    9394                }
    9495            }
     
    225226            let value = content;
    226227            switch (command.mode) {
    227                 case `print`:
    228                     value = value.split(`%0a`).join(`\n`).split(`%0A`).join(`\n`).split(`%0d`).join(``).split(`$0D`).join(``);
    229                     break;
    230                 case `html`:
    231                     value = value.split(`%0a`).join(`<br />`).split(`%0A`).join(`<br />`).split(`%0d`).join(``).split(`$0D`).join(``);
    232                     break;
     228            case `print`:
     229                value = value.split(`%0a`).join(`\n`).split(`%0A`).join(`\n`).split(`%0d`).join(``).split(`$0D`).join(``);
     230                break;
     231            case `html`:
     232                value = value.split(`%0a`).join(`<br />`).split(`%0A`).join(`<br />`).split(`%0d`).join(``).split(`$0D`).join(``);
     233                break;
    233234            }
    234235            targetRecord.value[targetRecord.index].content = value;
     
    260261                }
    261262                if ([`a`,
    262                         `blockquote`,
    263                         `button`,
    264                         `div`,
    265                         `fieldset`,
    266                         `file`,
    267                         `form`,
    268                         `h1`,
    269                         `h2`,
    270                         `h3`,
    271                         `h4`,
    272                         `h5`,
    273                         `h6`,
    274                         `hr`,
    275                         `img`,
    276                         `input`,
    277                         `label`,
    278                         `legend`,
    279                         `li`,
    280                         `p`,
    281                         `pre`,
    282                         `progress`,
    283                         `select`,
    284                         `span`,
    285                         `table`,
    286                         `tr`,
    287                         `td`,
    288                         `text`,
    289                         `textarea`,
    290                         `ul`
    291                     ].includes(keyword)) {
     263                    `blockquote`,
     264                    `button`,
     265                    `div`,
     266                    `fieldset`,
     267                    `file`,
     268                    `form`,
     269                    `h1`,
     270                    `h2`,
     271                    `h3`,
     272                    `h4`,
     273                    `h5`,
     274                    `h6`,
     275                    `hr`,
     276                    `image`,
     277                    `img`,
     278                    `input`,
     279                    `label`,
     280                    `legend`,
     281                    `li`,
     282                    `p`,
     283                    `pre`,
     284                    `progress`,
     285                    `select`,
     286                    `span`,
     287                    `table`,
     288                    `tr`,
     289                    `td`,
     290                    `text`,
     291                    `textarea`,
     292                    `ul`
     293                ].includes(keyword)) {
    292294                    if (compiler.nextTokenIs(`in`)) {
    293                         if (compiler.nextTokenIs(`body`)) {
    294                             compiler.next();
    295                             compiler.addCommand({
    296                                 domain: `browser`,
    297                                 keyword: `create`,
    298                                 lino,
    299                                 name: symbolRecord.name,
    300                                 parent: `body`
    301                             });
    302                             return true;
    303                         }
    304                         if (compiler.isSymbol()) {
     295                        if (compiler.nextIsSymbol()) {
    305296                            const parentRecord = compiler.getSymbolRecord();
    306297                            compiler.next();
     
    314305                            return true;
    315306                        }
     307                    } else {
     308                        const imports = compiler.imports;
     309                        if (imports.length > 0) {
     310                            const parent = imports[0].name;
     311                            compiler.addCommand({
     312                                domain: `browser`,
     313                                keyword: `create`,
     314                                lino,
     315                                name: symbolRecord.name,
     316                                parent,
     317                                imported: true
     318                            });
     319                            return true;
     320                        } else {
     321                            compiler.addCommand({
     322                                domain: `browser`,
     323                                keyword: `create`,
     324                                lino,
     325                                name: symbolRecord.name,
     326                                parent: `body`
     327                            });
     328                            return true;
     329                        }
    316330                    }
    317331                }
     
    324338            const targetRecord = program.getSymbolRecord(command.name);
    325339            switch (command.type) {
    326                 case `audioclip`:
    327                     targetRecord.value[targetRecord.index] = command.value;
    328                     break;
    329                 default:
    330                     let parent;
    331                     if (command.parent === `body`) {
    332                         parent = document.body;
    333                     } else {
    334                         const parentRecord = program.getSymbolRecord(command.parent);
    335                         if (!parentRecord.element[parentRecord.index]) {
    336                             program.runtimeError(command.pc, `Element ${parentRecord.name} does not exist.`);
    337                         }
    338                         parent = parentRecord.element[parentRecord.index];
    339                     }
    340                     targetRecord.element[targetRecord.index] = document.createElement(targetRecord.keyword);
    341                     if (!this.elementId) {
    342                         this.elementId = 0;
    343                     }
    344                     targetRecord.element[targetRecord.index].id = `ec-${targetRecord.name}-${targetRecord.index}-${this.elementId++}`;
    345                     if (targetRecord.keyword === `a`) {
    346                         targetRecord.element[targetRecord.index].setAttribute(`href`, `#`);
    347                     }
    348                     parent.appendChild(targetRecord.element[targetRecord.index]);
    349                     break;
     340            case `audioclip`:
     341                targetRecord.value[targetRecord.index] = command.value;
     342                break;
     343            default:
     344                let parent;
     345                if (command.parent === `body`) {
     346                    parent = document.body;
     347                } else {
     348                    const p = command.imported ? program.parent : program;
     349                    const parentRecord = p.getSymbolRecord(command.parent);
     350                    if (!parentRecord.element[parentRecord.index]) {
     351                        program.runtimeError(command.pc, `Element ${parentRecord.name} does not exist.`);
     352                    }
     353                    parent = parentRecord.element[parentRecord.index];
     354                }
     355                targetRecord.element[targetRecord.index] = document.createElement(targetRecord.keyword);
     356                if (!this.elementId) {
     357                    this.elementId = 0;
     358                }
     359                targetRecord.element[targetRecord.index].id = `ec-${targetRecord.name}-${targetRecord.index}-${this.elementId++}`;
     360                if (targetRecord.keyword === `a`) {
     361                    targetRecord.element[targetRecord.index].setAttribute(`href`, `#`);
     362                }
     363                parent.appendChild(targetRecord.element[targetRecord.index]);
     364                break;
    350365            }
    351366            return command.pc + 1;
     
    476491                            });
    477492                            return true;
     493                        } else {
     494                            compiler.addCommand({
     495                                domain: `browser`,
     496                                keyword: `get`,
     497                                action: `listStorage`,
     498                                lino,
     499                                target
     500                            });
     501                            return true;
    478502                        }
    479503                    }
     
    504528            const targetRecord = program.getSymbolRecord(command.target);
    505529            switch (command.action) {
    506                 case `getForm`:
    507                     const formRecord = program.getSymbolRecord(command.form);
    508                     const form = document.getElementById(formRecord.value[formRecord.index].content);
    509                     const data = new FormData(form);
    510                     const content = {};
    511                     for (const entry of data) {
    512                         content[entry[0]] = entry[1].replace(/\r/g, ``).replace(/\n/g, `%0a`);
    513                     }
    514                     targetRecord.value[targetRecord.index] = {
    515                         type: `constant`,
    516                         numeric: false,
    517                         content: JSON.stringify(content)
    518                     };
    519                     break;
    520                 case `getStorage`:
    521                     let value = window.localStorage.getItem(program.getValue(command.key));
    522                     if (typeof value === `undefined`) {
    523                         value = null;
    524                     }
    525                     targetRecord.value[targetRecord.index] = {
    526                         type: `constant`,
    527                         numeric: false,
    528                         content: value
    529                     };
    530                     break;
     530            case `getForm`:
     531                const formRecord = program.getSymbolRecord(command.form);
     532                const form = document.getElementById(formRecord.value[formRecord.index].content);
     533                const data = new FormData(form);
     534                const content = {};
     535                for (const entry of data) {
     536                    content[entry[0]] = entry[1].replace(/\r/g, ``).replace(/\n/g, `%0a`);
     537                }
     538                targetRecord.value[targetRecord.index] = {
     539                    type: `constant`,
     540                    numeric: false,
     541                    content: JSON.stringify(content)
     542                };
     543                break;
     544            case `listStorage`:
     545                const items = [];
     546                for (let i = 0, len = window.localStorage.length; i < len; i++) {
     547                    items.push(localStorage.key(i));
     548                }
     549                targetRecord.value[targetRecord.index] = {
     550                    type: `constant`,
     551                    numeric: false,
     552                    content: JSON.stringify(items)
     553                };
     554                break;
     555            case `getStorage`:
     556                let value = window.localStorage.getItem(program.getValue(command.key));
     557                if (typeof value === `undefined`) {
     558                    value = null;
     559                }
     560                targetRecord.value[targetRecord.index] = {
     561                    type: `constant`,
     562                    numeric: false,
     563                    content: value
     564                };
     565                break;
    531566            }
    532567            return command.pc + 1;
     
    612647            const type = compiler.nextToken();
    613648            switch (type) {
    614                 case `push`:
    615                 case `set`:
    616                 case `replace`:
    617                     compiler.next();
    618                     let url = ``;
    619                     let state = ``;
    620                     while (true) {
    621                         const token = compiler.getToken();
    622                         if (token === `url`) {
    623                             url = compiler.getNextValue();
    624                         } else if (token === `state`) {
    625                             state = compiler.getNextValue();
    626                         } else {
    627                             break;
    628                         }
    629                     }
    630                     compiler.addCommand({
    631                         domain: `browser`,
    632                         keyword: `history`,
    633                         lino,
    634                         type,
    635                         url,
    636                         state
    637                     });
    638                     return true;
    639                 case `pop`:
    640                 case `back`:
    641                 case `forward`:
    642                     compiler.next();
    643                     compiler.addCommand({
    644                         domain: `browser`,
    645                         keyword: `history`,
    646                         lino,
    647                         type
    648                     });
    649                     return true;
     649            case `push`:
     650            case `set`:
     651            case `replace`:
     652                compiler.next();
     653                let url = ``;
     654                let state = ``;
     655                while (true) {
     656                    const token = compiler.getToken();
     657                    if (token === `url`) {
     658                        url = compiler.getNextValue();
     659                    } else if (token === `state`) {
     660                        state = compiler.getNextValue();
     661                    } else {
     662                        break;
     663                    }
     664                }
     665                compiler.addCommand({
     666                    domain: `browser`,
     667                    keyword: `history`,
     668                    lino,
     669                    type,
     670                    url,
     671                    state
     672                });
     673                return true;
     674            case `pop`:
     675            case `back`:
     676            case `forward`:
     677                compiler.next();
     678                compiler.addCommand({
     679                    domain: `browser`,
     680                    keyword: `history`,
     681                    lino,
     682                    type
     683                });
     684                return true;
    650685            }
    651686            return false;
     
    663698            const url = program.getValue(command.url);
    664699            switch (command.type) {
    665                 case `push`:
    666                     if (!window.history.state) {
    667                         program.runtimeError(command.lino, `No state history; you need to call 'history set' on the parent`);
    668                         return 0;
    669                     }
    670                     window.history.pushState(state, ``, url);
    671                     break;
    672                 case `set`:
    673                 case `replace`:
    674                     window.history.replaceState(state, ``, url);
    675                     break;
    676                 case `pop`:
    677                 case `back`:
    678                     window.history.back();
    679                     break;
    680                 case `forward`:
    681                     window.history.forward();
    682                     break;
     700            case `push`:
     701                if (!window.history.state) {
     702                    program.runtimeError(command.lino, `No state history; you need to call 'history set' on the parent`);
     703                    return 0;
     704                }
     705                window.history.pushState(state, ``, url);
     706                break;
     707            case `set`:
     708            case `replace`:
     709                window.history.replaceState(state, ``, url);
     710                break;
     711            case `pop`:
     712            case `back`:
     713                window.history.back();
     714                break;
     715            case `forward`:
     716                window.history.forward();
     717                break;
    683718            }
    684719            return command.pc + 1;
     
    690725        compile: (compiler) => {
    691726            compiler.compileVariable(`browser`, `hr`, false, `dom`);
     727            return true;
     728        },
     729
     730        run: (program) => {
     731            return program[program.pc].pc + 1;
     732        }
     733    },
     734
     735    IMAGE: {
     736
     737        compile: (compiler) => {
     738            compiler.compileVariable(`browser`, `image`, false, `dom`);
    692739            return true;
    693740        },
     
    835882            const action = compiler.nextToken();
    836883            switch (action) {
    837                 case `change`:
     884            case `change`:
     885                compiler.next();
     886                if (compiler.isSymbol()) {
     887                    const symbol = compiler.getSymbolRecord();
    838888                    compiler.next();
    839                     if (compiler.isSymbol()) {
    840                         const symbol = compiler.getSymbolRecord();
    841                         compiler.next();
    842                         if (symbol.extra !== `dom`) {
    843                             return false;
    844                         }
    845                         compiler.addCommand({
    846                             domain: `browser`,
    847                             keyword: `on`,
    848                             lino,
    849                             action,
    850                             symbol: symbol.name
    851                         });
    852                         return compiler.completeHandler();
    853                     }
    854                     break;
    855                 case `click`:
    856                     if (compiler.nextTokenIs(`document`)) {
    857                         compiler.next();
    858                         compiler.addCommand({
    859                             domain: `browser`,
    860                             keyword: `on`,
    861                             lino,
    862                             action: `clickDocument`
    863                         });
    864                         return compiler.completeHandler();
    865                     }
    866                     if (compiler.isSymbol()) {
    867                         const symbol = compiler.getSymbolRecord();
    868                         compiler.next();
    869                         if (symbol.extra !== `dom`) {
    870                             return false;
    871                         }
    872                         compiler.addCommand({
    873                             domain: `browser`,
    874                             keyword: `on`,
    875                             lino,
    876                             action,
    877                             symbol: symbol.name
    878                         });
    879                         return compiler.completeHandler();
    880                     }
    881                     break;
    882                 case `key`:
    883                 case `leave`:
     889                    if (symbol.extra !== `dom`) {
     890                        return false;
     891                    }
     892                    compiler.addCommand({
     893                        domain: `browser`,
     894                        keyword: `on`,
     895                        lino,
     896                        action,
     897                        symbol: symbol.name
     898                    });
     899                    return compiler.completeHandler();
     900                }
     901                break;
     902            case `click`:
     903                if (compiler.nextTokenIs(`document`)) {
    884904                    compiler.next();
    885905                    compiler.addCommand({
     
    887907                        keyword: `on`,
    888908                        lino,
    889                         action
     909                        action: `clickDocument`
    890910                    });
    891911                    return compiler.completeHandler();
    892                 case `browser`:
    893                     if (compiler.nextTokenIs(`back`)) {
    894                         compiler.next();
    895                         compiler.addCommand({
    896                             domain: `browser`,
    897                             keyword: `on`,
    898                             lino,
    899                             action: `browserBack`
    900                         });
    901                         return compiler.completeHandler();
    902                     }
    903                     return false;
    904                 case `swipe`:
    905                     if ([`left`, `right`].includes(compiler.nextToken())) {
    906                         const direction = compiler.getToken();
    907                         compiler.next();
    908                         compiler.addCommand({
    909                             domain: `browser`,
    910                             keyword: `on`,
    911                             lino,
    912                             action: `swipe`,
    913                             direction
    914                         });
    915                         return compiler.completeHandler();
    916                     }
     912                }
     913                if (compiler.isSymbol()) {
     914                    const symbol = compiler.getSymbolRecord();
     915                    compiler.next();
     916                    if (symbol.extra !== `dom`) {
     917                        return false;
     918                    }
     919                    compiler.addCommand({
     920                        domain: `browser`,
     921                        keyword: `on`,
     922                        lino,
     923                        action,
     924                        symbol: symbol.name
     925                    });
     926                    return compiler.completeHandler();
     927                }
     928                break;
     929            case `key`:
     930            case `leave`:
     931                compiler.next();
     932                compiler.addCommand({
     933                    domain: `browser`,
     934                    keyword: `on`,
     935                    lino,
     936                    action
     937                });
     938                return compiler.completeHandler();
     939            case `browser`:
     940                if (compiler.nextTokenIs(`back`)) {
     941                    compiler.next();
     942                    compiler.addCommand({
     943                        domain: `browser`,
     944                        keyword: `on`,
     945                        lino,
     946                        action: `browserBack`
     947                    });
     948                    return compiler.completeHandler();
     949                }
     950                return false;
     951            case `swipe`:
     952                if ([`left`, `right`].includes(compiler.nextToken())) {
     953                    const direction = compiler.getToken();
     954                    compiler.next();
     955                    compiler.addCommand({
     956                        domain: `browser`,
     957                        keyword: `on`,
     958                        lino,
     959                        action: `swipe`,
     960                        direction
     961                    });
     962                    return compiler.completeHandler();
     963                }
    917964            }
    918965            compiler.addWarning(`Unrecognised syntax in 'on'`);
     
    923970            const command = program[program.pc];
    924971            switch (command.action) {
    925                 case `change`:
    926                     const changeItem = program.getSymbolRecord(command.symbol);
    927                     if (changeItem.keyword === `select`) {
    928                         const target = changeItem.element[changeItem.index];
    929                         target.targetPc = command.pc + 2;
    930                         target.addEventListener(`change`, function () {
    931                             try {
    932                                 program.run(target.targetPc);
    933                             } catch (err) {
    934                                 console.log(err.message);
    935                                 alert(err.message);
     972            case `change`:
     973                const changeItem = program.getSymbolRecord(command.symbol);
     974                if (changeItem.keyword === `select`) {
     975                    const target = changeItem.element[changeItem.index];
     976                    target.targetPc = command.pc + 2;
     977                    target.addEventListener(`change`, function () {
     978                        try {
     979                            program.run(target.targetPc);
     980                        } catch (err) {
     981                            console.log(err.message);
     982                            alert(err.message);
     983                        }
     984                        return false;
     985                    });
     986                }
     987                break;
     988            case `click`:
     989                const targetRecord = program.getSymbolRecord(command.symbol);
     990                targetRecord.element.forEach(function (target, index) {
     991                    target.targetRecord = targetRecord;
     992                    target.targetIndex = index;
     993                    target.targetPc = command.pc + 2;
     994                    target.onclick = function (event) {
     995                        event.stopPropagation();
     996                        if (program.length > 0) {
     997                            const eventTarget = event.target;
     998                            eventTarget.blur();
     999                            if (typeof eventTarget.targetRecord !== `undefined`) {
     1000                                eventTarget.targetRecord.index = eventTarget.targetIndex;
     1001                                setTimeout(function () {
     1002                                    EasyCoder.timestamp = Date.now();
     1003                                    program.run(eventTarget.targetPc);
     1004                                }, 1);
    9361005                            }
    937                             return false;
    938                         });
    939                     }
     1006                        }
     1007                        return false;
     1008                    };
     1009                });
     1010                break;
     1011            case `clickDocument`:
     1012                program.targetPc = command.pc + 2;
     1013                const interceptClickEvent = (e) => {
     1014                    EasyCoder.timestamp = Date.now();
     1015                    let target = e.target || e.srcElement;
     1016                    let href = ``;
     1017                    while (target.parentNode) {
     1018                        if (target.tagName === `A`) {
     1019                            href = target.href;
     1020                            program.docPath = href.slice(-(href.length - window.location.href.length));
     1021                            break;
     1022                        }
     1023                        target = target.parentNode;
     1024                    }
     1025                    while (target.parentNode) {
     1026                        if (target.id.indexOf(`ec-`) === 0) {
     1027                            let id = target.id.slice(3);
     1028                            let pos = id.indexOf(`-`);
     1029                            program.varName = id.slice(0, pos);
     1030                            id = id.slice(pos + 1);
     1031                            pos = id.indexOf(`-`);
     1032                            program.varIndex = parseInt(id.slice(0, pos));
     1033                            break;
     1034                        }
     1035                        target = target.parentNode;
     1036                    }
     1037                    if (href.indexOf(window.location.href) === 0) {
     1038                        program.run(program.targetPc);
     1039                        e.preventDefault();
     1040                    }
     1041                };
     1042                if (document.addEventListener) {
     1043                    document.addEventListener(`click`, interceptClickEvent);
     1044                } else if (document.attachEvent) {
     1045                    document.attachEvent(`onclick`, interceptClickEvent);
     1046                }
     1047                break;
     1048            case `swipe`:
     1049                let xDown;
     1050                const getTouches = (evt) => {
     1051                    return evt.touches || // browser API
     1052                            evt.originalEvent.touches; // jQuery
     1053                };
     1054                const handleTouchStart = (evt) => {
     1055                    const firstTouch = getTouches(evt)[0];
     1056                    xDown = firstTouch.clientX;
     1057                };
     1058                const handleTouchMove = (evt) => {
     1059                    evt.stopImmediatePropagation();
     1060                    if (!xDown) {
     1061                        return;
     1062                    }
     1063                    const xUp = evt.touches[0].clientX;
     1064                    const xDiff = xDown - xUp;
     1065                    if (Math.abs(xDiff) > 150) {
     1066                        xDown = null;
     1067                        if (xDiff > 0 && program.onSwipeLeft) {
     1068                            program.run(program.onSwipeLeft);
     1069                        } else if (xDiff < 0 && program.onSwipeRight) {
     1070                            program.run(program.onSwipeRight);
     1071                        }
     1072                    }
     1073                };
     1074                switch (command.direction) {
     1075                case `left`:
     1076                    program.onSwipeLeft = command.pc + 2;
    9401077                    break;
    941                 case `click`:
    942                     const targetRecord = program.getSymbolRecord(command.symbol);
    943                     targetRecord.element.forEach(function (target, index) {
    944                         target.targetRecord = targetRecord;
    945                         target.targetIndex = index;
    946                         target.targetPc = command.pc + 2;
    947                         target.onclick = function (event) {
    948                             event.stopPropagation();
    949                             if (program.length > 0) {
    950                                 const eventTarget = event.target;
    951                                 eventTarget.blur();
    952                                 if (typeof eventTarget.targetRecord !== `undefined`) {
    953                                     eventTarget.targetRecord.index = eventTarget.targetIndex;
    954                                     setTimeout(function () {
    955                                         EasyCoder.timestamp = Date.now();
    956                                         program.run(eventTarget.targetPc);
    957                                     }, 1);
    958                                 }
    959                             }
    960                             return false;
    961                         };
    962                     });
     1078                case `right`:
     1079                    program.onSwipeRight = command.pc + 2;
    9631080                    break;
    964                 case `clickDocument`:
    965                     program.targetPc = command.pc + 2;
    966                     const interceptClickEvent = (e) => {
    967                         EasyCoder.timestamp = Date.now();
    968                         let target = e.target || e.srcElement;
    969                         let href = ``;
    970                         while (target.parentNode) {
    971                             if (target.tagName === `A`) {
    972                                 href = target.href;
    973                                 program.docPath = href.slice(-(href.length - window.location.href.length));
    974                                 break;
    975                             }
    976                             target = target.parentNode;
    977                         }
    978                         while (target.parentNode) {
    979                             if (target.id.indexOf(`ec-`) === 0) {
    980                                 let id = target.id.slice(3);
    981                                 let pos = id.indexOf(`-`);
    982                                 program.varName = id.slice(0, pos);
    983                                 id = id.slice(pos + 1);
    984                                 pos = id.indexOf(`-`);
    985                                 program.varIndex = parseInt(id.slice(0, pos));
    986                                 break;
    987                             }
    988                             target = target.parentNode;
    989                         }
    990                         if (href.indexOf(window.location.href) === 0) {
    991                             program.run(program.targetPc);
    992                             e.preventDefault();
    993                         }
    994                     };
    995                     if (document.addEventListener) {
    996                         document.addEventListener(`click`, interceptClickEvent);
    997                     } else if (document.attachEvent) {
    998                         document.attachEvent(`onclick`, interceptClickEvent);
    999                     }
    1000                     break;
    1001                 case `swipe`:
    1002                     let xDown;
    1003                     const getTouches = (evt) => {
    1004                         return evt.touches || // browser API
    1005                             evt.originalEvent.touches; // jQuery
    1006                     };
    1007                     const handleTouchStart = (evt) => {
    1008                         const firstTouch = getTouches(evt)[0];
    1009                         xDown = firstTouch.clientX;
    1010                     };
    1011                     const handleTouchMove = (evt) => {
    1012                         evt.stopImmediatePropagation();
    1013                         if (!xDown) {
    1014                             return;
    1015                         }
    1016                         const xUp = evt.touches[0].clientX;
    1017                         const xDiff = xDown - xUp;
    1018                         if (Math.abs(xDiff) > 150) {
    1019                             xDown = null;
    1020                             if (xDiff > 0 && program.onSwipeLeft) {
    1021                                 program.run(program.onSwipeLeft);
    1022                             } else if (xDiff < 0 && program.onSwipeRight) {
    1023                                 program.run(program.onSwipeRight);
    1024                             }
    1025                         }
    1026                     };
    1027                     switch (command.direction) {
    1028                         case `left`:
    1029                             program.onSwipeLeft = command.pc + 2;
    1030                             break;
    1031                         case `right`:
    1032                             program.onSwipeRight = command.pc + 2;
    1033                             break;
    1034                     }
    1035                     document.addEventListener(`touchstart`, handleTouchStart, false);
    1036                     document.addEventListener(`touchmove`, handleTouchMove, false);
    1037                     break;
    1038                 case `key`:
    1039                     if (typeof document.onKeyListeners === `undefined`) {
    1040                         document.onKeyListeners = [];
    1041                     }
    1042                     if (!document.onKeyListeners.includes(program)) {
    1043                         document.onKeyListeners.push(program);
    1044                     }
    1045                     program.onKeyPc = command.pc + 2;
    1046                     document.onkeypress = function (event) {
    1047                         for (const program of document.onKeyListeners) {
    1048                             program.key = event.key;
    1049                             try {
    1050                                 setTimeout(function () {
    1051                                     program.run(program.onKeyPc);
    1052                                 }, 1);
    1053                             } catch (err) {
    1054                                 console.log(`Error: ${err.message}`);
    1055                             }
    1056                         }
    1057                         return true;
    1058                     };
    1059                     break;
    1060                 case `browserBack`:
    1061                     program.onBrowserBack = command.pc + 2;
    1062                     break;
    1063                 case `leave`:
    1064                     window.addEventListener(`beforeunload`, function () {
    1065                         program.run(command.pc + 2);
    1066                     });
    1067                     break;
    1068                 default:
    1069                     break;
     1081                }
     1082                document.addEventListener(`touchstart`, handleTouchStart, false);
     1083                document.addEventListener(`touchmove`, handleTouchMove, false);
     1084                break;
     1085            case `key`:
     1086                if (typeof document.onKeyListeners === `undefined`) {
     1087                    document.onKeyListeners = [];
     1088                }
     1089                if (!document.onKeyListeners.includes(program)) {
     1090                    document.onKeyListeners.push(program);
     1091                }
     1092                program.onKeyPc = command.pc + 2;
     1093                document.onkeypress = function (event) {
     1094                    for (const program of document.onKeyListeners) {
     1095                        program.key = event.key;
     1096                        try {
     1097                            setTimeout(function () {
     1098                                program.run(program.onKeyPc);
     1099                            }, 1);
     1100                        } catch (err) {
     1101                            console.log(`Error: ${err.message}`);
     1102                        }
     1103                    }
     1104                    return true;
     1105                };
     1106                break;
     1107            case `browserBack`:
     1108                program.onBrowserBack = command.pc + 2;
     1109                break;
     1110            case `leave`:
     1111                window.addEventListener(`beforeunload`, function () {
     1112                    program.run(command.pc + 2);
     1113                });
     1114                break;
     1115            default:
     1116                break;
    10701117            }
    10711118            return command.pc + 1;
     
    11751222        compile: (compiler) => {
    11761223            const lino = compiler.getLino();
    1177             if (compiler.nextIsSymbol()) {
    1178                 const child = compiler.getSymbolRecord();
    1179                 if (child.extra != `dom`) {
    1180                     compiler.warning(`'${child.name}' is not a DOM element`);
    1181                     return false;
    1182                 }
    1183                 if (compiler.nextTokenIs(`from`)) {
    1184                     if (compiler.nextIsSymbol()) {
    1185                         const parent = compiler.getSymbolRecord();
    1186                         if (parent.extra != `dom`) {
    1187                             compiler.warning(`'${parent.name}' is not a DOM element`);
    1188                             return false;
    1189                         }
    1190                         compiler.next();
    1191                         compiler.addCommand({
    1192                             domain: `browser`,
    1193                             keyword: `remove`,
    1194                             type: `removeElement`,
    1195                             lino,
    1196                             child: child.name,
    1197                             parent: parent.name
    1198                         });
    1199                         return true;
    1200                     }
    1201                 }
    1202                 return false;
     1224            if (compiler.nextTokenIs(`element`)) {
     1225                if (compiler.nextIsSymbol()) {
     1226                    const element = compiler.getSymbolRecord();
     1227                    if (element.extra != `dom`) {
     1228                        compiler.warning(`'${element.name}' is not a DOM element`);
     1229                        return false;
     1230                    }
     1231                    compiler.next();
     1232                    compiler.addCommand({
     1233                        domain: `browser`,
     1234                        keyword: `remove`,
     1235                        type: `removeElement`,
     1236                        lino,
     1237                        element: element.name
     1238                    });
     1239                    return true;
     1240                }
    12031241            }
    12041242            if (compiler.tokenIs(`attribute`)) {
     
    12231261                }
    12241262            }
     1263            const key = compiler.getValue();
     1264            if (compiler.tokenIs(`from`)) {
     1265                if (compiler.nextTokenIs(`storage`)) {
     1266                    compiler.next();
     1267                    compiler.addCommand({
     1268                        domain: `browser`,
     1269                        keyword: `remove`,
     1270                        type: `removeStorage`,
     1271                        key
     1272                    });
     1273                    return true;
     1274                }
     1275            }
    12251276            return false;
    12261277        },
     
    12311282            const command = program[program.pc];
    12321283            switch (command.type) {
    1233                 case `removeAttribute`:
    1234                     const attribute = program.getValue(command.attribute);
    1235                     const targetRecord = program.getSymbolRecord(command.target);
    1236                     target = targetRecord.element[targetRecord.index];
    1237                     target.removeAttribute(attribute);
    1238                     break;
    1239                 case `removeElement`:
    1240                     const childRecord = program.getSymbolRecord(command.child);
    1241                     const parentRecord = program.getSymbolRecord(command.parent);
    1242                     const child = childRecord.element[childRecord.index];
    1243                     const parent = parentRecord.element[parentRecord.index];
    1244                     parent.removeChild(child);
    1245                     break;
     1284            case `removeAttribute`:
     1285                const attribute = program.getValue(command.attribute);
     1286                const targetRecord = program.getSymbolRecord(command.target);
     1287                target = targetRecord.element[targetRecord.index];
     1288                target.removeAttribute(attribute);
     1289                break;
     1290            case `removeElement`:
     1291                const elementRecord = program.getSymbolRecord(command.element);
     1292                const element = elementRecord.element[elementRecord.index];
     1293                element.parentElement.removeChild(element);
     1294                break;
     1295            case `removeStorage`:
     1296                const key = program.getValue(command.key);
     1297                window.localStorage.removeItem(key);
     1298                break;
    12461299            }
    12471300            return command.pc + 1;
     
    12641317
    12651318        compile: (compiler) => {
    1266             if (compiler.nextTokenIs(`to`)) {
     1319            let name = null;
     1320            if (compiler.nextIsSymbol()) {
     1321                const symbolRecord = compiler.getSymbolRecord();
     1322                name = symbolRecord.name;
     1323                compiler.next();
     1324            }
     1325            if (compiler.tokenIs(`to`)) {
    12671326                const to = compiler.getNextValue();
    12681327                compiler.addCommand({
    12691328                    domain: `browser`,
    12701329                    keyword: `scroll`,
     1330                    name,
    12711331                    to
    12721332                });
     
    12791339            const command = program[program.pc];
    12801340            const to = program.getValue(command.to);
    1281             window.scrollTo(0, to);
    1282             // document.documentElement.pageYOffset = to;
     1341            if (command.name) {
     1342                const symbolRecord = program.getSymbolRecord(command.name);
     1343                symbolRecord.element[symbolRecord.index].scrollTo(0, to);
     1344            } else {
     1345                window.scrollTo(0, to);
     1346            }
    12831347            return command.pc + 1;
    12841348        }
     
    13941458                            const symbol = compiler.getSymbolRecord();
    13951459                            switch (symbol.keyword) {
    1396                                 case `button`:
    1397                                 case `input`:
    1398                                 case `span`:
    1399                                 case `label`:
    1400                                 case `legend`:
    1401                                     if (compiler.nextTokenIs(`to`)) {
    1402                                         const value = compiler.getNextValue();
    1403                                         compiler.addCommand({
    1404                                             domain: `browser`,
    1405                                             keyword: `set`,
    1406                                             lino,
    1407                                             type: `setText`,
    1408                                             symbolName: symbol.name,
    1409                                             value
    1410                                         });
    1411                                         return true;
    1412                                     }
    1413                                     break;
    1414                                 default:
    1415                                     break;
     1460                            case `button`:
     1461                            case `input`:
     1462                            case `span`:
     1463                            case `label`:
     1464                            case `legend`:
     1465                                if (compiler.nextTokenIs(`to`)) {
     1466                                    const value = compiler.getNextValue();
     1467                                    compiler.addCommand({
     1468                                        domain: `browser`,
     1469                                        keyword: `set`,
     1470                                        lino,
     1471                                        type: `setText`,
     1472                                        symbolName: symbol.name,
     1473                                        value
     1474                                    });
     1475                                    return true;
     1476                                }
     1477                                break;
     1478                            default:
     1479                                break;
    14161480                            }
    14171481                        }
     
    14221486                            const symbol = compiler.getSymbolRecord();
    14231487                            switch (symbol.keyword) {
    1424                                 case `input`:
    1425                                     if (compiler.nextTokenIs(`to`)) {
    1426                                         const value = compiler.getNextValue();
    1427                                         compiler.addCommand({
    1428                                             domain: `browser`,
    1429                                             keyword: `set`,
    1430                                             lino,
    1431                                             type: `setSize`,
    1432                                             symbolName: symbol.name,
    1433                                             value
    1434                                         });
    1435                                         return true;
    1436                                     }
     1488                            case `input`:
     1489                                if (compiler.nextTokenIs(`to`)) {
     1490                                    const value = compiler.getNextValue();
     1491                                    compiler.addCommand({
     1492                                        domain: `browser`,
     1493                                        keyword: `set`,
     1494                                        lino,
     1495                                        type: `setSize`,
     1496                                        symbolName: symbol.name,
     1497                                        value
     1498                                    });
     1499                                    return true;
     1500                                }
    14371501                            }
    14381502                        }
     
    15581622            let cssId;
    15591623            switch (command.type) {
    1560                 case `setContentVar`:
    1561                     const sourceVar = program.getSymbolRecord(command.source);
    1562                     targetVar = program.getSymbolRecord(command.target);
    1563                     const source = document.getElementById(sourceVar.value[sourceVar.index].content);
    1564                     target = targetVar.element[targetVar.index];
    1565                     if (!target) {
    1566                         targetId = program.getValue(targetVar.value[targetVar.index]);
    1567                         target = document.getElementById(targetId);
    1568                     }
    1569                     target.innerHTML = source.innerHTML;
     1624            case `setContentVar`:
     1625                const sourceVar = program.getSymbolRecord(command.source);
     1626                targetVar = program.getSymbolRecord(command.target);
     1627                const source = document.getElementById(sourceVar.value[sourceVar.index].content);
     1628                target = targetVar.element[targetVar.index];
     1629                if (!target) {
     1630                    targetId = program.getValue(targetVar.value[targetVar.index]);
     1631                    target = document.getElementById(targetId);
     1632                }
     1633                target.innerHTML = source.innerHTML;
     1634                break;
     1635            case `setContent`:
     1636                value = program.getValue(command.value);
     1637                targetVar = program.getSymbolRecord(command.target);
     1638                target = targetVar.element[targetVar.index];
     1639                if (!target) {
     1640                    cssId = targetVar.value[targetVar.index].content;
     1641                    if (!cssId) {
     1642                        program.runtimeError(command.lino,
     1643                            `Variable '${targetVar.name}' has not been attached to a DOM element.`);
     1644                        return 0;
     1645                    }
     1646                    target = document.getElementById(cssId);
     1647                }
     1648                targetVar.element[targetVar.index] = target;
     1649                switch (targetVar.keyword) {
     1650                case `text`:
     1651                case `textarea`:
     1652                    target.value = value;
    15701653                    break;
    1571                 case `setContent`:
    1572                     value = program.getValue(command.value);
    1573                     targetVar = program.getSymbolRecord(command.target);
    1574                     target = targetVar.element[targetVar.index];
    1575                     if (!target) {
    1576                         cssId = targetVar.value[targetVar.index].content;
    1577                         if (!cssId) {
    1578                             program.runtimeError(command.lino,
    1579                                 `Variable '${targetVar.name}' has not been attached to a DOM element.`);
    1580                             return 0;
    1581                         }
    1582                         target = document.getElementById(cssId);
    1583                     }
    1584                     targetVar.element[targetVar.index] = target;
    1585                     switch (targetVar.keyword) {
    1586                         case `text`:
    1587                         case `textarea`:
    1588                             target.value = value;
    1589                             break;
    1590                         case `input`:
    1591                             target.value = value;
    1592                             break;
    1593                         default:
    1594                             target.innerHTML = value;
    1595                             break;
    1596                     }
     1654                case `input`:
     1655                    target.value = value;
    15971656                    break;
    1598                 case `setId`:
    1599                     symbol = program.getSymbolRecord(command.symbolName);
     1657                default:
     1658                    target.innerHTML = value;
     1659                    break;
     1660                }
     1661                break;
     1662            case `setId`:
     1663                symbol = program.getSymbolRecord(command.symbolName);
     1664                target = symbol.element[symbol.index];
     1665                if (!target) {
     1666                    targetId = program.getValue(symbol.value[symbol.index]);
     1667                    target = document.getElementById(targetId);
     1668                }
     1669                target.id = program.getValue(command.value);
     1670                break;
     1671            case `setText`:
     1672                symbol = program.getSymbolRecord(command.symbolName);
     1673                target = symbol.element[symbol.index];
     1674                if (!target) {
     1675                    targetId = program.getValue(symbol.value[symbol.index]);
     1676                    target = document.getElementById(targetId);
     1677                }
     1678                value = program.getValue(command.value);
     1679                switch (symbol.keyword) {
     1680                case `button`:
     1681                case `span`:
     1682                case `label`:
     1683                case `legend`:
     1684                    target.innerHTML = value;
     1685                    break;
     1686                case `input`:
     1687                    target.value = value;
     1688                    break;
     1689                default:
     1690                    break;
     1691                }
     1692                break;
     1693            case `setSize`:
     1694                symbol = program.getSymbolRecord(command.symbolName);
     1695                if (symbol.keyword === `input`) {
    16001696                    target = symbol.element[symbol.index];
    16011697                    if (!target) {
     
    16031699                        target = document.getElementById(targetId);
    16041700                    }
    1605                     target.id = program.getValue(command.value);
     1701                    target.size = program.getValue(command.value);
     1702                } else {
     1703                    program.runtimeError(command.lino, `Inappropriate variable type '${symbol.name}'`);
     1704                }
     1705                break;
     1706            case `setAttribute`:
     1707                symbol = program.getSymbolRecord(command.symbolName);
     1708                target = symbol.element[symbol.index];
     1709                if (!target) {
     1710                    targetId = program.getValue(symbol.value[symbol.index]);
     1711                    target = document.getElementById(targetId);
     1712                }
     1713                const attributeName = program.getValue(command.attributeName);
     1714                if (command.attributeValue.type === `boolean`) {
     1715                    target.setAttribute(attributeName, command.attributeValue.content);
     1716                } else {
     1717                    target.setAttribute(attributeName, program.getValue(command.attributeValue));
     1718                }
     1719                break;
     1720            case `setStyle`:
     1721            case `setStyles`:
     1722                symbol = program.getSymbolRecord(command.symbolName);
     1723                target = symbol.element[symbol.index];
     1724                if (!target) {
     1725                    const symbolElement = symbol.value[symbol.index];
     1726                    if (!symbolElement.type) {
     1727                        program.runtimeError(command.lino, `Variable '${symbol.name}' is not attached to a DOM element.`);
     1728                        return 0;
     1729                    }
     1730                    targetId = program.getValue(symbolElement);
     1731                    target = document.getElementById(targetId);
     1732                }
     1733                const styleValue = program.getValue(command.styleValue);
     1734                if (!symbol.value[symbol.index]) {
     1735                    program.runtimeError(command.lino, `Variable '${symbol.name}' has not been assigned.`);
     1736                    return 0;
     1737                }
     1738                switch (command.type) {
     1739                case `setStyle`:
     1740                    target.style[command.styleName.content] = styleValue;
    16061741                    break;
    1607                 case `setText`:
    1608                     symbol = program.getSymbolRecord(command.symbolName);
    1609                     target = symbol.element[symbol.index];
    1610                     if (!target) {
    1611                         targetId = program.getValue(symbol.value[symbol.index]);
    1612                         target = document.getElementById(targetId);
    1613                     }
    1614                     value = program.getValue(command.value);
    1615                     switch (symbol.keyword) {
    1616                         case `button`:
    1617                         case `span`:
    1618                         case `label`:
    1619                         case `legend`:
    1620                             target.innerHTML = value;
    1621                             break;
    1622                         case `input`:
    1623                             target.value = value;
    1624                             break;
    1625                         default:
    1626                             break;
    1627                     }
     1742                case `setStyles`:
     1743                    target.style.cssText = styleValue;
    16281744                    break;
    1629                 case `setSize`:
    1630                     symbol = program.getSymbolRecord(command.symbolName);
    1631                     if (symbol.keyword === `input`) {
    1632                         target = symbol.element[symbol.index];
    1633                         if (!target) {
    1634                             targetId = program.getValue(symbol.value[symbol.index]);
    1635                             target = document.getElementById(targetId);
    1636                         }
    1637                         target.size = program.getValue(command.value);
    1638                     } else {
    1639                         program.runtimeError(command.lino, `Inappropriate variable type '${symbol.name}'`);
    1640                     }
    1641                     break;
    1642                 case `setAttribute`:
    1643                     symbol = program.getSymbolRecord(command.symbolName);
    1644                     target = symbol.element[symbol.index];
    1645                     if (!target) {
    1646                         targetId = program.getValue(symbol.value[symbol.index]);
    1647                         target = document.getElementById(targetId);
    1648                     }
    1649                     const attributeName = program.getValue(command.attributeName);
    1650                     if (command.attributeValue.type === `boolean`) {
    1651                         target.setAttribute(attributeName, command.attributeValue.content);
    1652                     } else {
    1653                         target.setAttribute(attributeName, program.getValue(command.attributeValue));
    1654                     }
    1655                     break;
    1656                 case `setStyle`:
    1657                 case `setStyles`:
    1658                     symbol = program.getSymbolRecord(command.symbolName);
    1659                     target = symbol.element[symbol.index];
    1660                     if (!target) {
    1661                         const symbolElement = symbol.value[symbol.index];
    1662                         if (!symbolElement.type) {
    1663                             program.runtimeError(command.lino, `Variable '${symbol.name}' is not attached to a DOM element.`);
    1664                             return 0;
    1665                         }
    1666                         targetId = program.getValue(symbolElement);
    1667                         target = document.getElementById(targetId);
    1668                     }
    1669                     const styleValue = program.getValue(command.styleValue);
    1670                     if (!symbol.value[symbol.index]) {
    1671                         program.runtimeError(command.lino, `Variable '${symbol.name}' has not been assigned.`);
    1672                         return 0;
    1673                     }
    1674                     switch (command.type) {
    1675                         case `setStyle`:
    1676                             target.style[command.styleName.content] = styleValue;
    1677                             break;
    1678                         case `setStyles`:
    1679                             target.style.cssText = styleValue;
    1680                             break;
    1681                     }
    1682                     break;
    1683                 case `setBodyStyle`:
    1684                     const bodyStyleValue = program.getValue(command.styleValue);
    1685                     document.body.style[command.styleName.content] = bodyStyleValue.content;
    1686                     break;
    1687                 case `setTitle`:
    1688                     document.title = program.getValue(command.value);
    1689                     break;
    1690                 case `setDefault`:
    1691                     const selectRecord = program.getSymbolRecord(command.name);
    1692                     value = program.getValue(command.value);
    1693                     const element = selectRecord.element[selectRecord.index];
    1694                     for (let n = 0; n < element.options.length; n++) {
    1695                         if (element.options[n].value === value) {
    1696                             element.selectedIndex = n;
    1697                             break;
    1698                         }
    1699                     }
    1700                     break;
    1701                 default:
    1702                     break;
     1745                }
     1746                break;
     1747            case `setBodyStyle`:
     1748                const bodyStyleValue = program.getValue(command.styleValue);
     1749                document.body.style[command.styleName.content] = bodyStyleValue.content;
     1750                break;
     1751            case `setTitle`:
     1752                document.title = program.getValue(command.value);
     1753                break;
     1754            case `setDefault`:
     1755                const selectRecord = program.getSymbolRecord(command.name);
     1756                value = program.getValue(command.value);
     1757                const element = selectRecord.element[selectRecord.index];
     1758                for (let n = 0; n < element.options.length; n++) {
     1759                    if (element.options[n].value === value) {
     1760                        element.selectedIndex = n;
     1761                        break;
     1762                    }
     1763                }
     1764                break;
     1765            default:
     1766                break;
    17031767            }
    17041768            return command.pc + 1;
     
    18031867            const command = program[program.pc];
    18041868            switch (command.variant) {
    1805                 case `setup`:
    1806                     console.log(`Set up tracer`);
     1869            case `setup`:
     1870                console.log(`Set up tracer`);
     1871                program.tracer = {
     1872                    variables: command.variables,
     1873                    alignment: command.alignment
     1874                };
     1875                break;
     1876            case `run`:
     1877                console.log(`Run tracer`);
     1878                if (!program.tracer) {
    18071879                    program.tracer = {
    1808                         variables: command.variables,
    1809                         alignment: command.alignment
     1880                        variables: [],
     1881                        alignment: `horizontal`
    18101882                    };
    1811                     break;
    1812                 case `run`:
    1813                     console.log(`Run tracer`);
    1814                     if (!program.tracer) {
    1815                         program.tracer = {
    1816                             variables: [],
    1817                             alignment: `horizontal`
    1818                         };
    1819                     }
    1820                     program.tracing = true;
    1821                     program.stop = false;
    1822                     break;
     1883                }
     1884                program.tracing = true;
     1885                program.stop = false;
     1886                break;
    18231887            }
    18241888            return program.pc + 1;
     
    19231987                        const command = program.ajaxCommand;
    19241988                        switch (this.status) {
    1925                             case 200:
    1926                                 program.run(command.pc + 1);
    1927                                 break;
    1928                             case 0:
    1929                                 break;
    1930                             default:
    1931                                 let error = ``;
    1932                                 try {
    1933                                     error = JSON.parse(this.responseText ? this.responseText : `{}`);
    1934                                 } catch (err) {
    1935                                     program.runtimeError(command.lino, `Can't parse JSON`);
    1936                                     return 0;
    1937                                 }
    1938                                 try {
    1939                                     program.runtimeError(command.lino, error.message);
    1940                                 } catch (err) {
    1941                                     program.reportError(err, program);
    1942                                 }
    1943                                 break;
     1989                        case 200:
     1990                            program.run(command.pc + 1);
     1991                            break;
     1992                        case 0:
     1993                            break;
     1994                        default:
     1995                            let error = ``;
     1996                            try {
     1997                                error = JSON.parse(this.responseText ? this.responseText : `{}`);
     1998                            } catch (err) {
     1999                                program.runtimeError(command.lino, `Can't parse JSON`);
     2000                                return 0;
     2001                            }
     2002                            try {
     2003                                program.runtimeError(command.lino, error.message);
     2004                            } catch (err) {
     2005                                program.reportError(err, program);
     2006                            }
     2007                            break;
    19442008                        }
    19452009                    }
     
    19552019    getHandler: (name) => {
    19562020        switch (name) {
    1957             case `a`:
    1958                 return EasyCoder_Browser.A;
    1959             case `alert`:
    1960                 return EasyCoder_Browser.Alert;
    1961             case `attach`:
    1962                 return EasyCoder_Browser.Attach;
    1963             case `audioclip`:
    1964                 return EasyCoder_Browser.Audioclip;
    1965             case `blockquote`:
    1966                 return EasyCoder_Browser.BLOCKQUOTE;
    1967             case `button`:
    1968                 return EasyCoder_Browser.BUTTON;
    1969             case `clear`:
    1970                 return EasyCoder_Browser.Clear;
    1971             case `convert`:
    1972                 return EasyCoder_Browser.Convert;
    1973             case `create`:
    1974                 return EasyCoder_Browser.Create;
    1975             case `disable`:
    1976                 return EasyCoder_Browser.Disable;
    1977             case `div`:
    1978                 return EasyCoder_Browser.DIV;
    1979             case `enable`:
    1980                 return EasyCoder_Browser.Enable;
    1981             case `fieldset`:
    1982                 return EasyCoder_Browser.FIELDSET;
    1983             case `file`:
    1984                 return EasyCoder_Browser.FILE;
    1985             case `form`:
    1986                 return EasyCoder_Browser.FORM;
    1987             case `get`:
    1988                 return EasyCoder_Browser.Get;
    1989             case `h1`:
    1990                 return EasyCoder_Browser.H1;
    1991             case `h2`:
    1992                 return EasyCoder_Browser.H2;
    1993             case `h3`:
    1994                 return EasyCoder_Browser.H3;
    1995             case `h4`:
    1996                 return EasyCoder_Browser.H4;
    1997             case `h5`:
    1998                 return EasyCoder_Browser.H5;
    1999             case `h6`:
    2000                 return EasyCoder_Browser.H6;
    2001             case `history`:
    2002                 return EasyCoder_Browser.History;
    2003             case `hr`:
    2004                 return EasyCoder_Browser.HR;
    2005             case `img`:
    2006                 return EasyCoder_Browser.IMG;
    2007             case `input`:
    2008                 return EasyCoder_Browser.INPUT;
    2009             case `label`:
    2010                 return EasyCoder_Browser.LABEL;
    2011             case `legend`:
    2012                 return EasyCoder_Browser.LEGEND;
    2013             case `li`:
    2014                 return EasyCoder_Browser.LI;
    2015             case `location`:
    2016                 return EasyCoder_Browser.Location;
    2017             case `mail`:
    2018                 return EasyCoder_Browser.Mail;
    2019             case `on`:
    2020                 return EasyCoder_Browser.On;
    2021             case `p`:
    2022                 return EasyCoder_Browser.P;
    2023             case `play`:
    2024                 return EasyCoder_Browser.Play;
    2025             case `pre`:
    2026                 return EasyCoder_Browser.PRE;
    2027             case `progress`:
    2028                 return EasyCoder_Browser.PROGRESS;
    2029             case `put`:
    2030                 return EasyCoder_Browser.Put;
    2031             case `remove`:
    2032                 return EasyCoder_Browser.Remove;
    2033             case `select`:
    2034                 return EasyCoder_Browser.SELECT;
    2035             case `scroll`:
    2036                 return EasyCoder_Browser.Scroll;
    2037             case `section`:
    2038                 return EasyCoder_Browser.SECTION;
    2039             case `set`:
    2040                 return EasyCoder_Browser.Set;
    2041             case `span`:
    2042                 return EasyCoder_Browser.SPAN;
    2043             case `table`:
    2044                 return EasyCoder_Browser.TABLE;
    2045             case `tr`:
    2046                 return EasyCoder_Browser.TR;
    2047             case `td`:
    2048                 return EasyCoder_Browser.TD;
    2049             case `textarea`:
    2050                 return EasyCoder_Browser.TEXTAREA;
    2051             case `trace`:
    2052                 return EasyCoder_Browser.Trace;
    2053             case `ul`:
    2054                 return EasyCoder_Browser.UL;
    2055             case `upload`:
    2056                 return EasyCoder_Browser.Upload;
    2057             default:
    2058                 return false;
     2021        case `a`:
     2022            return EasyCoder_Browser.A;
     2023        case `alert`:
     2024            return EasyCoder_Browser.Alert;
     2025        case `attach`:
     2026            return EasyCoder_Browser.Attach;
     2027        case `audioclip`:
     2028            return EasyCoder_Browser.Audioclip;
     2029        case `blockquote`:
     2030            return EasyCoder_Browser.BLOCKQUOTE;
     2031        case `button`:
     2032            return EasyCoder_Browser.BUTTON;
     2033        case `clear`:
     2034            return EasyCoder_Browser.Clear;
     2035        case `convert`:
     2036            return EasyCoder_Browser.Convert;
     2037        case `create`:
     2038            return EasyCoder_Browser.Create;
     2039        case `disable`:
     2040            return EasyCoder_Browser.Disable;
     2041        case `div`:
     2042            return EasyCoder_Browser.DIV;
     2043        case `enable`:
     2044            return EasyCoder_Browser.Enable;
     2045        case `fieldset`:
     2046            return EasyCoder_Browser.FIELDSET;
     2047        case `file`:
     2048            return EasyCoder_Browser.FILE;
     2049        case `form`:
     2050            return EasyCoder_Browser.FORM;
     2051        case `get`:
     2052            return EasyCoder_Browser.Get;
     2053        case `h1`:
     2054            return EasyCoder_Browser.H1;
     2055        case `h2`:
     2056            return EasyCoder_Browser.H2;
     2057        case `h3`:
     2058            return EasyCoder_Browser.H3;
     2059        case `h4`:
     2060            return EasyCoder_Browser.H4;
     2061        case `h5`:
     2062            return EasyCoder_Browser.H5;
     2063        case `h6`:
     2064            return EasyCoder_Browser.H6;
     2065        case `history`:
     2066            return EasyCoder_Browser.History;
     2067        case `hr`:
     2068            return EasyCoder_Browser.HR;
     2069        case `image`:
     2070            return EasyCoder_Browser.IMAGE;
     2071        case `img`:
     2072            return EasyCoder_Browser.IMG;
     2073        case `input`:
     2074            return EasyCoder_Browser.INPUT;
     2075        case `label`:
     2076            return EasyCoder_Browser.LABEL;
     2077        case `legend`:
     2078            return EasyCoder_Browser.LEGEND;
     2079        case `li`:
     2080            return EasyCoder_Browser.LI;
     2081        case `location`:
     2082            return EasyCoder_Browser.Location;
     2083        case `mail`:
     2084            return EasyCoder_Browser.Mail;
     2085        case `on`:
     2086            return EasyCoder_Browser.On;
     2087        case `p`:
     2088            return EasyCoder_Browser.P;
     2089        case `play`:
     2090            return EasyCoder_Browser.Play;
     2091        case `pre`:
     2092            return EasyCoder_Browser.PRE;
     2093        case `progress`:
     2094            return EasyCoder_Browser.PROGRESS;
     2095        case `put`:
     2096            return EasyCoder_Browser.Put;
     2097        case `remove`:
     2098            return EasyCoder_Browser.Remove;
     2099        case `select`:
     2100            return EasyCoder_Browser.SELECT;
     2101        case `scroll`:
     2102            return EasyCoder_Browser.Scroll;
     2103        case `section`:
     2104            return EasyCoder_Browser.SECTION;
     2105        case `set`:
     2106            return EasyCoder_Browser.Set;
     2107        case `span`:
     2108            return EasyCoder_Browser.SPAN;
     2109        case `table`:
     2110            return EasyCoder_Browser.TABLE;
     2111        case `tr`:
     2112            return EasyCoder_Browser.TR;
     2113        case `td`:
     2114            return EasyCoder_Browser.TD;
     2115        case `textarea`:
     2116            return EasyCoder_Browser.TEXTAREA;
     2117        case `trace`:
     2118            return EasyCoder_Browser.Trace;
     2119        case `ul`:
     2120            return EasyCoder_Browser.UL;
     2121        case `upload`:
     2122            return EasyCoder_Browser.Upload;
     2123        default:
     2124            return false;
    20592125        }
    20602126    },
     
    20862152                }
    20872153                switch (symbolRecord.keyword) {
    2088                     case `file`:
    2089                     case `input`:
    2090                     case `select`:
    2091                     case `textarea`:
    2092                         return {
    2093                             domain: `browser`,
    2094                                 type: symbolRecord.keyword,
    2095                                 value: symbolRecord.name
    2096                         };
     2154                case `file`:
     2155                case `input`:
     2156                case `select`:
     2157                case `textarea`:
     2158                    return {
     2159                        domain: `browser`,
     2160                        type: symbolRecord.keyword,
     2161                        value: symbolRecord.name
     2162                    };
    20972163                }
    20982164                return null;
     
    21392205                return null;
    21402206            }
     2207            if (type === `style`) {
     2208                const style = compiler.getNextValue();
     2209                if (compiler.tokenIs(`of`)) {
     2210                    if (compiler.nextIsSymbol()) {
     2211                        const symbolRecord = compiler.getSymbolRecord();
     2212                        if (symbolRecord.extra === `dom`) {
     2213                            compiler.next();
     2214                            return {
     2215                                domain: `browser`,
     2216                                type,
     2217                                style,
     2218                                target: symbolRecord.name
     2219                            };
     2220                        }
     2221                    }
     2222                }
     2223                return null;
     2224            }
    21412225            if (type === `confirm`) {
    21422226                const text = compiler.getNextValue();
     
    22112295            }
    22122296            switch (type) {
    2213                 case `scroll`:
    2214                     if (compiler.nextTokenIs(`position`)) {
    2215                         compiler.next();
    2216                         return {
    2217                             domain: `browser`,
    2218                             type: `scrollPosition`
    2219                         };
    2220                     }
    2221                     return null;
    2222                 case `document`:
    2223                     if (compiler.nextTokenIs(`path`)) {
    2224                         compiler.next();
    2225                         return {
    2226                             domain: `browser`,
    2227                             type: `docPath`
    2228                         };
    2229                     }
    2230                     return null;
    2231                 case `parent`:
    2232                     switch (compiler.nextToken()) {
    2233                         case `name`:
    2234                             compiler.next();
    2235                             return {
    2236                                 domain: `browser`,
    2237                                     type: `varName`
    2238                             };
    2239                         case `index`:
    2240                             compiler.next();
    2241                             return {
    2242                                 domain: `browser`,
    2243                                     type: `varIndex`
    2244                             };
    2245                     }
    2246                     return null;
    2247                 case `history`:
    2248                     if (compiler.nextTokenIs(`state`)) {
    2249                         compiler.next();
    2250                         return {
    2251                             domain: `browser`,
    2252                             type: `historyState`
    2253                         };
    2254                     }
    2255                     return null;
     2297            case `scroll`:
     2298                if (compiler.nextTokenIs(`position`)) {
     2299                    compiler.next();
     2300                    return {
     2301                        domain: `browser`,
     2302                        type: `scrollPosition`
     2303                    };
     2304                }
     2305                return null;
     2306            case `document`:
     2307                if (compiler.nextTokenIs(`path`)) {
     2308                    compiler.next();
     2309                    return {
     2310                        domain: `browser`,
     2311                        type: `docPath`
     2312                    };
     2313                }
     2314                return null;
     2315            case `parent`:
     2316                switch (compiler.nextToken()) {
     2317                case `name`:
     2318                    compiler.next();
     2319                    return {
     2320                        domain: `browser`,
     2321                        type: `varName`
     2322                    };
     2323                case `index`:
     2324                    compiler.next();
     2325                    return {
     2326                        domain: `browser`,
     2327                        type: `varIndex`
     2328                    };
     2329                }
     2330                return null;
     2331            case `history`:
     2332                if (compiler.nextTokenIs(`state`)) {
     2333                    compiler.next();
     2334                    return {
     2335                        domain: `browser`,
     2336                        type: `historyState`
     2337                    };
     2338                }
     2339                return null;
    22562340            }
    22572341            return null;
     
    22642348            let content;
    22652349            switch (value.type) {
    2266                 case `file`:
     2350            case `file`:
     2351            case `input`:
     2352            case `select`:
     2353            case `textarea`:
     2354                symbolRecord = program.getSymbolRecord(value.value);
     2355                target = symbolRecord.element[symbolRecord.index];
     2356                return {
     2357                    type: `constant`,
     2358                    numeric: false,
     2359                    content: target.value
     2360                };
     2361            case `exists`:
     2362                symbolRecord = program.getSymbolRecord(value.value);
     2363                return {
     2364                    domain: `browser`,
     2365                    type: `boolean`,
     2366                    content: typeof symbolRecord.element[symbolRecord.index] !== `undefined`
     2367                };
     2368            case `mobile`:
     2369                return {
     2370                    domain: `browser`,
     2371                    type: `boolean`,
     2372                    content: (typeof window.orientation !== `undefined`) || (navigator.userAgent.indexOf(`IEMobile`) !== -1)
     2373                };
     2374            case `portrait`:
     2375                return {
     2376                    domain: `browser`,
     2377                    type: `boolean`,
     2378                    content: document.documentElement.clientWidth < document.documentElement.clientHeight
     2379                };
     2380            case `landscape`:
     2381                return {
     2382                    domain: `browser`,
     2383                    type: `boolean`,
     2384                    content: document.documentElement.clientWidth >= document.documentElement.clientHeight
     2385                };
     2386            case `br`:
     2387                return {
     2388                    type: `constant`,
     2389                    numeric: false,
     2390                    content: decodeURIComponent(`%3Cbr%20%2F%3E`)
     2391                };
     2392            case `attributeOf`:
     2393                symbolRecord = program.getSymbolRecord(value.symbol);
     2394                const attribute = program.getValue(value.attribute);
     2395                target = symbolRecord.element[symbolRecord.index];
     2396                if (attribute.indexOf(`data-`) === 0) {
     2397                    return program.getSimpleValue(target.dataset[attribute.substr(5)]);
     2398                }
     2399                return program.getSimpleValue(target[attribute]);
     2400            case `style`:
     2401                symbolRecord = program.getSymbolRecord(value.target);
     2402                const style = program.getValue(value.style);
     2403                target = symbolRecord.element[symbolRecord.index];
     2404                return program.getSimpleValue(target.style[style]);
     2405            case `confirm`:
     2406                return {
     2407                    type: `boolean`,
     2408                    content: window.confirm(program.getValue(value.text))
     2409                };
     2410            case `prompt`:
     2411                const text = program.getValue(value.text);
     2412                const pre = program.getValue(value.pre);
     2413                return {
     2414                    type: `constant`,
     2415                    numeric: false,
     2416                    content: window.prompt(text, pre)
     2417                };
     2418            case `contentOf`:
     2419                symbolRecord = program.getSymbolRecord(value.symbol);
     2420                target = symbolRecord.element[symbolRecord.index];
     2421                switch (symbolRecord.keyword) {
    22672422                case `input`:
    2268                 case `select`:
    22692423                case `textarea`:
    2270                     symbolRecord = program.getSymbolRecord(value.value);
    2271                     target = symbolRecord.element[symbolRecord.index];
    2272                     return {
    2273                         type: `constant`,
    2274                             numeric: false,
    2275                             content: target.value
    2276                     };
    2277                 case `exists`:
    2278                     symbolRecord = program.getSymbolRecord(value.value);
    2279                     return {
    2280                         domain: `browser`,
    2281                             type: `boolean`,
    2282                             content: typeof symbolRecord.element[symbolRecord.index] !== `undefined`
    2283                     };
    2284                 case `mobile`:
    2285                     return {
    2286                         domain: `browser`,
    2287                             type: `boolean`,
    2288                             content: (typeof window.orientation !== `undefined`) || (navigator.userAgent.indexOf(`IEMobile`) !== -1)
    2289                     };
    2290                 case `portrait`:
    2291                     return {
    2292                         domain: `browser`,
    2293                             type: `boolean`,
    2294                             content: document.documentElement.clientWidth < document.documentElement.clientHeight
    2295                     };
    2296                 case `landscape`:
    2297                     return {
    2298                         domain: `browser`,
    2299                             type: `boolean`,
    2300                             content: document.documentElement.clientWidth >= document.documentElement.clientHeight
    2301                     };
    2302                 case `br`:
    2303                     return {
    2304                         type: `constant`,
    2305                             numeric: false,
    2306                             content: decodeURIComponent(`%3Cbr%20%2F%3E`)
    2307                     };
    2308                 case `attributeOf`:
    2309                     symbolRecord = program.getSymbolRecord(value.symbol);
    2310                     const attribute = program.getValue(value.attribute);
    2311                     target = symbolRecord.element[symbolRecord.index];
    2312                     if (attribute.indexOf(`data-`) === 0) {
    2313                         return program.getSimpleValue(target.dataset[attribute.substr(5)]);
    2314                     }
    2315                     return program.getSimpleValue(target[attribute]);
    2316                 case `confirm`:
    2317                     return {
    2318                         type: `boolean`,
    2319                             content: window.confirm(program.getValue(value.text))
    2320                     };
    2321                 case `prompt`:
    2322                     const text = program.getValue(value.text);
    2323                     const pre = program.getValue(value.pre);
    2324                     return {
    2325                         type: `constant`,
    2326                             numeric: false,
    2327                             content: window.prompt(text, pre)
    2328                     };
    2329                 case `contentOf`:
    2330                     symbolRecord = program.getSymbolRecord(value.symbol);
    2331                     target = symbolRecord.element[symbolRecord.index];
    2332                     switch (symbolRecord.keyword) {
    2333                         case `input`:
    2334                         case `textarea`:
    2335                             content = target.value;
    2336                             break;
    2337                         case `pre`:
    2338                             content = target.innerHTML;
    2339                             break;
    2340                         default:
    2341                             content = target.innerHTML.split(`\n`).join(``);
    2342                             break;
    2343                     }
    2344                     return {
    2345                         type: `constant`,
    2346                             numeric: false,
    2347                             content
    2348                     };
    2349                 case `selectedItem`:
    2350                     symbolRecord = program.getSymbolRecord(value.symbol);
    2351                     element = symbolRecord.value[symbolRecord.index].content;
    2352                     target = document.getElementById(element);
    2353                     return {
    2354                         type: `constant`,
    2355                             numeric: false,
    2356                             content: target.options[target.selectedIndex].text
    2357                     };
    2358                 case `widthOf`:
    2359                     symbolRecord = program.getSymbolRecord(value.symbol);
    2360                     content = symbolRecord.element[symbolRecord.index].offsetWidth;
    2361                     return {
    2362                         type: `constant`,
    2363                             numeric: true,
    2364                             content
    2365                     };
    2366                 case `heightOf`:
    2367                     symbolRecord = program.getSymbolRecord(value.symbol);
    2368                     content = symbolRecord.element[symbolRecord.index].offsetHeight;
    2369                     return {
    2370                         type: `constant`,
    2371                             numeric: true,
    2372                             content
    2373                     };
    2374                 case `color`:
    2375                     const styleValue = program.value.evaluate(program, value.value).content;
    2376                     const hex = styleValue.toString(16).padStart(6, `0`);
    2377                     return {
    2378                         type: `constant`,
    2379                             numeric: false,
    2380                             content: `#${hex}`
    2381                     };
    2382                 case `docPath`:
    2383                     return {
    2384                         type: `constant`,
    2385                             numeric: false,
    2386                             content: program.docPath
    2387                     };
    2388                 case `location`:
    2389                     return {
    2390                         type: `constant`,
    2391                             numeric: false,
    2392                             content: window.location.href
    2393                     };
    2394                 case `historyState`:
    2395                     return {
    2396                         type: `constant`,
    2397                             numeric: false,
    2398                             content: window.history.state
    2399                     };
    2400                 case `scrollPosition`:
    2401                     return {
    2402                         type: `constant`,
    2403                             numeric: true,
    2404                             content: scrollPosition
    2405                     };
    2406                 case `varName`:
    2407                     return {
    2408                         type: `constant`,
    2409                             numeric: false,
    2410                             content: program.varName
    2411                     };
    2412                 case `varIndex`:
    2413                     return {
    2414                         type: `constant`,
    2415                             numeric: true,
    2416                             content: program.varIndex
    2417                     };
    2418                 case `key`:
    2419                     return {
    2420                         type: `constant`,
    2421                             numeric: false,
    2422                             content: program.key
    2423                     };
     2424                    content = target.value;
     2425                    break;
     2426                case `pre`:
     2427                    content = target.innerHTML;
     2428                    break;
     2429                default:
     2430                    content = target.innerHTML.split(`\n`).join(``);
     2431                    break;
     2432                }
     2433                return {
     2434                    type: `constant`,
     2435                    numeric: false,
     2436                    content
     2437                };
     2438            case `selectedItem`:
     2439                symbolRecord = program.getSymbolRecord(value.symbol);
     2440                element = symbolRecord.value[symbolRecord.index].content;
     2441                target = document.getElementById(element);
     2442                return {
     2443                    type: `constant`,
     2444                    numeric: false,
     2445                    content: target.options[target.selectedIndex].text
     2446                };
     2447            case `widthOf`:
     2448                symbolRecord = program.getSymbolRecord(value.symbol);
     2449                content = symbolRecord.element[symbolRecord.index].offsetWidth;
     2450                return {
     2451                    type: `constant`,
     2452                    numeric: true,
     2453                    content
     2454                };
     2455            case `heightOf`:
     2456                symbolRecord = program.getSymbolRecord(value.symbol);
     2457                content = symbolRecord.element[symbolRecord.index].offsetHeight;
     2458                return {
     2459                    type: `constant`,
     2460                    numeric: true,
     2461                    content
     2462                };
     2463            case `color`:
     2464                const styleValue = program.value.evaluate(program, value.value).content;
     2465                const hex = styleValue.toString(16).padStart(6, `0`);
     2466                return {
     2467                    type: `constant`,
     2468                    numeric: false,
     2469                    content: `#${hex}`
     2470                };
     2471            case `docPath`:
     2472                return {
     2473                    type: `constant`,
     2474                    numeric: false,
     2475                    content: program.docPath
     2476                };
     2477            case `location`:
     2478                return {
     2479                    type: `constant`,
     2480                    numeric: false,
     2481                    content: window.location.href
     2482                };
     2483            case `historyState`:
     2484                return {
     2485                    type: `constant`,
     2486                    numeric: false,
     2487                    content: window.history.state
     2488                };
     2489            case `scrollPosition`:
     2490                return {
     2491                    type: `constant`,
     2492                    numeric: true,
     2493                    content: scrollPosition
     2494                };
     2495            case `varName`:
     2496                return {
     2497                    type: `constant`,
     2498                    numeric: false,
     2499                    content: program.varName
     2500                };
     2501            case `varIndex`:
     2502                return {
     2503                    type: `constant`,
     2504                    numeric: true,
     2505                    content: program.varIndex
     2506                };
     2507            case `key`:
     2508                return {
     2509                    type: `constant`,
     2510                    numeric: false,
     2511                    content: program.key
     2512                };
    24242513            }
    24252514        }
     
    24612550        test: (program, condition) => {
    24622551            switch (condition.type) {
    2463                 case `confirm`:
    2464                     return confirm(program.getValue(condition.value));
    2465                 case `focus`:
    2466                     const elementRecord = program.getSymbolRecord(condition.element);
    2467                     return elementRecord.element[elementRecord.index] === document.activeElement;
     2552            case `confirm`:
     2553                return confirm(program.getValue(condition.value));
     2554            case `focus`:
     2555                const elementRecord = program.getSymbolRecord(condition.element);
     2556                return elementRecord.element[elementRecord.index] === document.activeElement;
    24682557            }
    24692558        }
  • easycoder/trunk/plugins/codemirror.js

    r2089142 r2102119  
    99            case `init`:
    1010                const mode = compiler.nextToken();
    11                 compiler.next();
     11                let profile = ``;
     12                if (compiler.nextTokenIs(`profile`)) {
     13                    profile = compiler.getNextValue();
     14                }
    1215                compiler.addCommand({
    1316                    domain: `codemirror`,
     
    1518                    lino,
    1619                    action,
    17                     mode
     20                    mode,
     21                    profile
    1822                });
    1923                return true;
     
    9195                            program.require(`js`, `https://codemirror.net/lib/codemirror.js`,
    9296                                function () {
    93                                     program.require(`js`, `/wp-content/plugins/easycoder/plugins/codemirror-ecs.js`,
    94                                         function () {
    95                                             program.run(command.pc + 1);
    96                                         });
     97                                    if (command.profile) {
     98                                        program.require(`js`, program.getValue(command.profile),
     99                                            function () {
     100                                                program.run(command.pc + 1);
     101                                            });
     102                                    } else {
     103                                        program.run(command.pc + 1);
     104                                    }
    97105                                });
    98106                        });
  • easycoder/trunk/plugins/json.js

    r2089142 r2102119  
    66            const lino = compiler.getLino();
    77            const request = compiler.nextToken();
     8            let item;
    89            switch (request) {
    910            case `set`:
     
    139140                break;
    140141            case `add`:
    141                 const item = compiler.getNextValue();
     142                item = compiler.getNextValue();
    142143                if (compiler.tokenIs(`to`)) {
    143144                    if (compiler.nextIsSymbol()) {
     
    158159                }
    159160                break;
     161            case `split`:
     162                item = compiler.getNextValue();
     163                if (compiler.tokenIs(`into`)){
     164                    if (compiler.nextIsSymbol()) {
     165                        const targetRecord = compiler.getSymbolRecord();
     166                        if (targetRecord.keyword === `variable`) {
     167                            compiler.next();
     168                            compiler.addCommand({
     169                                domain: `json`,
     170                                keyword: `json`,
     171                                lino,
     172                                request,
     173                                item,
     174                                target: targetRecord.name
     175                            });
     176                            return true;
     177                        }
     178                    }
     179                }
     180                break;
    160181            }
    161             compiler.addWarning(`Unrecognised syntax in json`);
     182            compiler.addWarning(`Unrecognised json command syntax`);
    162183            return false;
    163184        },
     
    211232            case `sort`:
    212233                targetRecord = program.getSymbolRecord(command.target);
    213                 let a = JSON.parse(program.getValue(targetRecord.value[targetRecord.index])).sort();
     234                const list = program.getValue(targetRecord.value[targetRecord.index]);
     235                content = list ? JSON.stringify(JSON.parse(list).sort()) : list;
    214236                targetRecord.value[targetRecord.index] = {
    215237                    type: `constant`,
    216238                    numeric: false,
    217                     content: JSON.stringify(a)
     239                    content
    218240                };
    219241                break;
     
    288310                content = program.getValue(command.item);
    289311                targetRecord = program.getSymbolRecord(command.target);
    290                 record = JSON.parse(targetRecord.value[targetRecord.index].content);
     312                const existing = targetRecord.value[targetRecord.index].content;
     313                record = existing ? JSON.parse(existing) : [];
    291314                record.push(content);
    292315                targetRecord.value[targetRecord.index].content = JSON.stringify(record);
     316                break;
     317            case `split`:
     318                content = program.getValue(command.item);
     319                targetRecord = program.getSymbolRecord(command.target);
     320                targetRecord.value[targetRecord.index].content = content.split(`\n`);
    293321                break;
    294322            }
  • easycoder/trunk/plugins/rest.js

    r2089142 r2102119  
    4646                }
    4747                const url = compiler.getValue();
     48                if (!url) {
     49                    throw new Error(command.lino, `No URL present`);
     50                }
    4851                let target = null;
    4952                if (compiler.tokenIs(`giving`)) {
     
    8285            const command = program[program.pc];
    8386            const url = program.getValue(command.url);
    84             const ajax = new XMLHttpRequest();
    85             ajax.command = command;
    86             ajax.onreadystatechange = function () {
    87                 //        console.log(`readyState:${ajax.readyState}, status:${ajax.status}`);
    88                 if (ajax.readyState === 4) {
    89                     const command = ajax.command;
    90                     switch (this.status) {
    91                     case 200:
    92                     case 201:
    93                         var content = this.responseText;
    94                         if (content.length > 0 && ![`[`, `{`].includes(content.charAt(0))) {
    95                             content = program.decode(content);
    96                         }
    97                         if (command.target) {
    98                             const targetRecord = program.getSymbolRecord(command.target);
    99                             targetRecord.value[targetRecord.index] = {
    100                                 type: `constant`,
    101                                 numeric: false,
    102                                 content
    103                             };
    104                         }
    105                         program.run(command.pc + 1);
    106                         break;
    107                     case 0:
    108                         break;
    109                     default:
    110                         if (command.onError) {
    111                             program.errorMessage = this.responseText;
    112                             program.run(command.onError);
    113                         } else {
    114                             const error = this.responseText;
    115                             program.runtimeError(command.lino, error);
    116                         }
    117                         break;
    118                     }
     87            const request = new XMLHttpRequest();
     88            request.command = command;
     89
     90            request.onload = function () {
     91                var content = request.responseText;
     92                if (content.length > 0 && ![`[`, `{`].includes(content.charAt(0))) {
     93                    content = program.decode(content);
     94                }
     95                if (command.target) {
     96                    const targetRecord = program.getSymbolRecord(command.target);
     97                    targetRecord.value[targetRecord.index] = {
     98                        type: `constant`,
     99                        numeric: false,
     100                        content
     101                    };
     102                }
     103                program.run(command.pc + 1);
     104            };
     105
     106            request.onerror = function () {
     107                if (command.onError) {
     108                    program.errorMessage = this.responseText;
     109                    program.run(command.onError);
     110                } else {
     111                    const error = this.responseText;
     112                    program.runtimeError(command.lino, error);
    119113                }
    120114            };
    121             if (!url) {
    122                 program.runtimeError(command.lino, `No URL present`);
    123             }
    124             const path = url.startsWith(`http`) ? url :
    125                 `${window.location.origin}/wp-content/plugins/easycoder/rest.php/${url}`;
     115
     116            const path = url.startsWith(`http`) ? url : `${window.location.origin}/${EasyCoder_Plugins.rest()}/${url}`;
    126117            switch (command.request) {
    127118            case `get`:
    128119                // console.log(`GET from ${path}`);
    129                 ajax.open(`GET`, path);
    130                 ajax.send();
     120                request.open(`GET`, path);
     121                request.send();
    131122                break;
    132123            case `post`:
    133124                const value = program.getValue(command.value);
    134125                console.log(`POST to ${path}`);
    135                 ajax.open(`POST`, path);
     126                request.open(`POST`, path);
    136127                if (value.charAt(0) === `{` || !isNaN(value)) {
    137                     ajax.setRequestHeader(`Content-Type`, `application/json; charset=UTF-8`);
     128                    request.setRequestHeader(`Content-Type`, `application/json; charset=UTF-8`);
    138129                    //            console.log(`value=${value}`);
    139                     ajax.send(value.charAt(0) === `{` ? value : value.toString());
     130                    request.send(value.charAt(0) === `{` ? value : value.toString());
    140131                } else {
    141                     ajax.setRequestHeader(`Content-Type`, `application/text; charset=UTF-8`);
     132                    request.setRequestHeader(`Content-Type`, `application/text; charset=UTF-8`);
    142133                    // console.log(`value=${program.encode(value)}`);
    143                     ajax.send(program.encode(value));
     134                    request.send(program.encode(value));
    144135                }
    145136                break;
  • easycoder/trunk/plugins/svg.js

    r2052097 r2102119  
    157157                    }
    158158                }
    159                 const container = document.getElementById(parentRecord.value[parentRecord.index].content);
     159                const container = parentRecord.element[parentRecord.index];
    160160                const element = document.createElementNS(ns, command.type);
    161161                symbolRecord.element[symbolRecord.index] = element;
  • easycoder/trunk/readme.txt

    r2089142 r2102119  
    5353
    5454== Changelog ==
     55
     56= 2.3.1 7-jun-2019 =
     57* Bug fixes & updates to support learn-to-code
    5558
    5659= 2.3.0 16-may-2019 =
  • easycoder/trunk/rest.php

    r2038748 r2102119  
    7070                                foreach ($files as $file) {
    7171                                        if (strpos($file, '.') !== 0) {
    72                                                 if (!is_dir("$path/$file")) {
    73                                                         if ($flag) {
    74                                                                 print ',';
    75                                                         } else {
    76                                                                 $flag = true;
    77                                                         }
    78                                                         $ext = substr($file, strrpos($file, '.') + 1);
    79                                                         $type = $ext;
    80                                                         switch (strtolower($ext)) {
    81                                                         case 'jpg':
    82                                                         case 'png':
    83                                                         case 'gif':
    84                                                                 $type = 'img';
    85                                                                 break;
    86                                                         }
    87                                                         print "{\"name\":\"$file\",\"type\":\"$type\"}";
    88                                                 }
    89                                         }
     72                                            if (!is_dir("$path/$file")) {
     73                                                    if ($flag) {
     74                                                            print ',';
     75                                                    } else {
     76                                                            $flag = true;
     77                                                    }
     78                                                    $type = 'file';
     79                                                    $p = strrpos($file, '.');
     80                                                    if ($p > 0) {
     81                                                            $ext = substr($file, $p + 1);
     82                                                            $type = $ext;
     83                                                            switch (strtolower($ext)) {
     84                                                                    case 'jpg':
     85                                                                    case 'png':
     86                                                                    case 'gif':
     87                                                                            $type = 'img';
     88                                                                            break;
     89                                                            }
     90                                                    }
     91                                            }
     92                                            print "{\"name\":\"$file\",\"type\":\"$type\"}";
     93                                    }
    9094                                }
    9195                                print ']';
Note: See TracChangeset for help on using the changeset viewer.