[JSCodeGen] asm end; bloc that the transpiler leave as is

Issue #237 resolved
Toky Olivier Razanakotonarivo created an issue

Hello Eric,

First of all, I would like to thank you for your response to all my questions/requests.

Today, I would like to know how to tell the transpiler to leave as is all the text inside an “asm end” bloc. For example, I have this code:

asm
//Compression of the zip file https://lemonadejs.net/v2/lemonade.js
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.lemonade=t()}(this,function(){"use strict";var e=null;e="undefined"==typeof document||document.lemonadejs?document.lemonadejs:document.lemonadejs={queue:[],container:{}};var t=function(e){return e instanceof Element||e instanceof HTMLDocument},n=function(e,t){return v.element(e,this,t)},r=function(t,n){var r=null,i=null;if(i=t.lemon){if(i.queue)for(;r=i.queue.shift();)e.queue.push(r);"function"==typeof i.self.onload&&e.queue.push(i.self.onload.bind(i.self,t))}if(document.body.contains(n)&&e&&e.queue&&e.queue.length)for(;r=e.queue.shift();)r()},i=function(e){var t=null;if("function"==typeof e.val)t=e.val();else if("SELECT"==e.tagName&&e.getAttribute("multiple")){t=[];for(var n=0;n<e.options.length;n++)e.options[n].selected&&t.push(e.options[n].value)}else t="checkbox"==e.type?e.checked&&e.getAttribute("value")?e.value:e.checked:e.getAttribute("contenteditable")?e.innerHTML:e.value;return t},l=function(e,t,n){if("value"===n){if("function"==typeof e.val)e.val()!=t&&e.val(t);else if("SELECT"==e.tagName&&e.getAttribute("multiple"))for(var r=0;r<e.children.length;r++)e.children[r].selected=t.indexOf(e.children[r].value)>=0;else"checkbox"==e.type?e.checked=!!t&&"0"!==t&&"false"!==t:"radio"==e.type?(e.checked=!1,e.value==t&&(e.checked=!0)):e.getAttribute&&e.getAttribute("contenteditable")?e.innerHTML!=t&&(e.innerHTML=t):e.value=t}else void 0!==e[n]||"function"==typeof t||"object"==typeof t?e[n]=t:e.setAttribute(n,t)},o=function(e){return Function("self",'"use strict";return ('+e+")")(this)},s=function(e,t){var n,r,i,s,a,f=null;if(r=this.tracking[e]){for(f=0,n=this.self;f<r.length;f++)s=r[f].element,i=o.call(n,r[f].v),"@loop"==(a=r[f].property)?d.call(s,i,n,this.components):s.self?s.self[a]=i:(l(s,i,a),this.tag&&"self.value"==r[f].v&&this.tag["@bind"]&&this.self.parent[this.tag["@bind"]]!==i&&(this.self.parent[this.tag["@bind"]]=i));t||"function"!=typeof n.onchange||n.onchange.call(s,e,r,n)}},a=function(e){var t=this,n=!0;Object.defineProperty(this.self,e,{set:function(r){t.state[e]=r,s.call(t,e,n),n=!1},get:function(){return t.state[e]},configurable:!0,enumerable:!0})},f=function(e,t,n){var r=this.self,i=o.call(r,t.v);if(void 0===i&&(i=""),"textContent"==n){var s=document.createTextNode(i);e.childNodes[0]?e.insertBefore(s,e.childNodes[0].splitText(t.p)):e.appendChild(s)}else if("@loop"==n)var s=e;else{var s=e;l(e,i,n)}var f=t.v.match(/self\.([a-zA-Z0-9_].*?)*/g);if(f&&f.length)for(var u=0;u<f.length;u++){var c=f[u].replace("self.",""),h=!1,p=this.self[c];void 0===p&&(p=""),this.tracking[c]||(this.tracking[c]=[],h=!0),this.tracking[c].push({element:s,property:n,v:t.v}),h&&a.call(this,c),this.self[c]=p}},u=function(e,t){var n=[],r=0,i=function(e,t,i,l){return n.push({p:i-r,v:t}),r+=e.length,""};if(e.getAttribute&&e.getAttribute(t)?e.setAttribute(t,e.getAttribute(t).replace(/{{(.*?)}}/g,i)):"string"==typeof e[t]&&e[t]&&(e[t]=e[t].replace(/{{(.*?)}}/g,i)),n.length){1!=n.length||"textContent"!=t||e.innerText||(t="innerHTML");for(var l=n.length-1;l>=0;l--)f.call(this,e,n[l],t)}},c=function(e){var t={},n=null,r=this.attributes;if(r&&r.length)for(var i=0;i<r.length;i++)n=r[i].name,!0==e&&void 0!==this[n]?t[n]=this[n]:t[n]=r[i].value;return t},h=function(e){var t=this,n=null,r=c.call(e);if(this.components){for(var l=Object.keys(this.components),o=0;o<l.length;o++)this.components[l[o].toUpperCase()]=this.components[l[o]];var a=e.tagName;"function"==typeof(n=this.components[a])&&(e.handler=n)}(e.getAttribute("@loop")||e.getAttribute("lm-loop"))&&!n&&(n=!0,e.parent=e),n&&(e.self={},e.template=e.innerHTML,e.innerHTML="");var l=Object.keys(r);if(l.length)for(var o=0;o<l.length;o++)if(e.handler||"on"!=l[o].substring(0,2)){var d=r[l[o]].replace("self.","");"@ready"==l[o]||"lm-ready"==l[o]?(this.queue.push(Function("self",r[l[o]]).bind(e,this.self)),e.removeAttribute(l[o])):"@ref"==l[o]||"lm-ref"==l[o]?(this.self[d]=e.self?e.self:e,e.removeAttribute(l[o])):"@bind"==l[o]||"lm-bind"==l[o]?(e.oninput=(function(e,t){this.state[t]=i(e),s.call(this,t)}).bind(this,e,d),f.call(this,e,{v:r[l[o]]},"value"),e[l[o]]=d,e.removeAttribute(l[o])):"@loop"==l[o]||"lm-loop"==l[o]?(f.call(this,e,{v:r[l[o]]},"@loop"),e.loop=this.self[d],e.removeAttribute(l[o])):(u.call(this,e,l[o]),document.dictionary&&(n=v.translate(r[l[o]]))&&e.setAttribute(l[o],n))}else{let g=l[o].toLowerCase(),m=r[l[o]];e.removeAttribute(g),e.addEventListener(l[o].substring(2),function(e){Function("self","e",m).call(this,t.self,e)})}if(e.children.length){for(var n=[],o=0;o<e.children.length;o++)n.push(e.children[o]);for(var o=0;o<n.length;o++)h.call(this,n[o])}else e.textContent&&(u.call(this,e,"textContent"),document.dictionary&&(n=v.translate(e.innerText))&&(e.innerText=n));var b=e.handler;if("function"==typeof b){if(void 0===e.loop){var $=e.parentNode,y=v.setProperties.call(e.self,c.call(e,!0),!0);p(y,"parent",this.self),v.render(b,$,y,e.template,e,t.components)}e.remove()}},p=function(e,t,n){Object.defineProperty(e,t,{enumerable:!1,configurable:!0,get:function(){return n}})},d=function(e,t,r){var i=null;this.parent||(this.parent=this.parentNode);var l=this.parent,o=this.handler||n,i=this.template,s=[];if(e.length)for(let a=0;a<e.length;a++){let f=e[a].el;f||(p(e[a],"parent",t),f=v.render(o,l,e[a],i,null,r)),"false"===l.getAttribute("unique")&&p(e[a],"el",null),s.push(f)}for(;l.children[0];)l.children[0].remove();for(;i=s.shift();)l.appendChild(i)},v={};return v.render=function(e,n,i,l,o,s){var a,f=e;if(!t(n))return console.log("Not valid DOM"),!1;if(i||(i={}),"function"==typeof e&&("function"==typeof(a=e)&&/^class\s/.test(Function.prototype.toString.call(a))?(e=new e(i),e=v.element(e.render(l,s),e)):e=e.call(i,l,s),!t(e)))return console.log("Component did not returned a valid DOM"),!1;if("ROOT"==e.tagName)for(e.lemon.root=[];e.firstChild;)e.lemon.root.push(e.firstChild),o?n.insertBefore(e.firstChild,o):n.appendChild(e.firstChild);else o?n.insertBefore(e,o):n.appendChild(e);return r(e,n),e.lemon.component=f,o&&(e.lemon.tag=o),e},v.element=function(e,n,r){var i={self:n||{},state:{},tracking:{},queue:[]};if(r&&(i.components=r),t(e))var l=e;else{e=(e=e.replace(/(<([A-Z]{1}[a-zA-Z0-9_-]+)[^>]*)(\/|\/.{1})>/gm,"$1></$2>")).replace(/<>/gi,"<root>").replace(/<\/>/gi,"</root>").trim();var l=document.createElement("template");if(l.innerHTML=e,l.content?l=l.content:(l=document.createElement("div")).innerHTML=e,l.childNodes.length>1){console.error("Single root required");return}l=l.firstChild}return h.call(i,l),p(n,"refresh",function(e){v.refresh.call(i,e)}),p(n,"el",l),l.lemon=i,l},v.template=v.element,v.refresh=function(e){if(void 0!==e)s.call(this,e);else{let t=this.self.el;if("ROOT"==t.tagName)for(t=this.root,v.render(this.component,t[0].parentNode,this.self,null,t[0]);t[0];)t.shift().remove();else v.render(this.component,t.parentNode,this.self,null,t),t.parentNode.removeChild(t)}},v.blender=function(e,t,n){return v.render(v.element(e,t),n,t)},v.apply=function(e,t,n){v.element(e,t,n),r(e,e)},v.getProperties=function(e){var t={};for(var n in e)t[n]=this[n];return t},v.setProperties=function(e,t){for(var n in e)(this.hasOwnProperty(n)||t)&&(this[n]=e[n]);return this},v.resetProperties=function(e){for(var t in e)this[t]=""},v.get=function(t){return e.container[t]},v.set=function(t,n,r){if(e.container[t]=n,"function"==typeof n&&!0===r){e.container[t].storage=!0;var i=window.localStorage.getItem(t);i&&n(i=JSON.parse(i))}},v.dispatch=function(t,n){var r=e.container[t];"function"==typeof r&&(r(n),!0===r.storage&&window.localStorage.setItem(t,JSON.stringify(n)))},v.translate=function(e){if("^^["==e.substr(0,3)&&"]^^"==e.substr(-3))return e=e.replace("^^[","").replace("]^^",""),document.dictionary[e]||e},v.component=class{constructor(){}},v});
end;

If I compile it, an error is thrown:

Syntax Error: Invalid character (found "&") [line: 3]

Is there any switch that the compiler or transplier leave as is this particular asm bloc? It tries to scan etc and there are errors etc even if it’s a working js code.

Thank you!

Comments (5)

  1. Eric Grange repo owner

    Hi,

    Yes, the asm blocks are still parsed to find and update ‘@' references.
    I guess the tokenizer stumbles on '&' when used in an operator (and as a stop character) rather than as identifier start character

  2. Toky Olivier Razanakotonarivo reporter

    Thank you @Eric, but it’s not only ‘&', ‘\’ also too, etc. Just tried it. You don’t want to add some switch so that the compiler don’t parse an asm block? Sometime, the asm block contains ‘@', or another invalid characters (in comments or in the code). It will be really helpful to copy and paste one functionnal js code in the asm block (leave it as is, without modifications) and we call or use it in pascal.

    asm {$P-}
       //This is an asm block that the compiler leave as is (without parsing or compilation)
       //It can contain @ & \ etc.... 
       var a = 15;
       var b = "@one string \'";
    end;
    
    var a: integer;
    asm @a = a; end;
    

  3. Eric Grange repo owner

    If you want raw js blocks, the simpler solution would probably not be to have them as an asm block (which is meant to be parsed), but maybe as something that is meant to be linked ?

    That said the parser is aware of JS strings, so your first snippet with @one in a string will be ok.
    I’ll have a look at that highlight.js version and update the tokenizer (probably for an inline regexp)

  4. Eric Grange repo owner

    Committed support for backslash in the tokenizer.

    However even with a compiler switch, some Javascript could still throw a spanner in the asm block by having some code with an “end;”, so I guess having a way to link/specify a raw js file directly would be best.

    What about reusing the {$LINK} ?

    • {$LINK highlight.js} would ask the codegen to link the specified js file, placing it verbatim before codegen’ed js (and if multiple $LINK are present, by order of appearance). If the same file is linked multiple times, it’s placed only once.
    • {$LINK INLINE highlight.js} would ask the codegen to place the highlight.js inline, as in a non-parsed asm block, multiple $LINK INLINE would insert the js multiple times

    Not sure if having the ability to control the ordering of $LINK would be useful (and if so, how ?)

  5. Log in to comment