Ir para o conteúdo

metajs — a new language? — Aurélio A. Heckert — Noosfero UFBA

Aurélio A. Heckert

Programador estudando educação.
 Voltar a Blog
Tela cheia

metajs — a new language?

17 de Setembro de 2014, 19:38 , por Feed RSS do(a) Aurélio A. Heckert - 22 comentários | Ninguém está seguindo este artigo ainda.
Visualizado 31 vezes

No. :-)

This is a javascript extension, that only use comments to provide meta-features. I named my project files as *.metajs only to let clear: it may be a valid javascript code, but will not work as expected. This looks like a good idea, right? The features are code inclusion from another file and macros. The compiler is a BASH function, but lets talk about the features in detail first.

Why i did it? Because I was going crazy scrolling my source code with more then thousand lines, and with weird expressions that i wont put in variables or functions, for may js13kGames entry Gravity.

Including another file

When we want to minify a project code we need it all in one file, but, when we have some more "laborious", is a good idea to modularize it in some files. This explain why the including feature. The include does not only copy the content, it also put it all in a closure. This approach is also better then including many files inside the html, through <script>, because its content scope is protected and its declared variables will be valid only for this module and its sub-modules. As i said, it allows sub-modules, because it works recursively.

Well, lets see my real case, the game Gravity. I have this files:
audio.metajs draw.metajs gravity.metajs objects-update.metajs riffwave.metajs stars.metajs

Inside of some of this files we find special comments like this, on gravity.metajs:

var bgW = Math.round(bgZ*2.9);
var bgH = bgZ*2;
//include stars

(window.onresize = function() {

This "//include X" will search for a file named X.metajs and will replace the comment with its content, inside a closure.

Compiling gravity.metajs (the main file), we get:

(function() { // Start gravity
  ... gravity code ...
  (function() { // Start audio
    ... audio code ...
    var RIFFWAVE;
    (function() { // Start riffwave
      ... riffwave code ...
    })(); // End riffwave
    ... audio code ...
  })(); // End audio
  ... gravity code ...
  (function() { // Start stars
    ... stars code ...
  })(); // End stars
  ... gravity code ...
  (function() { // Start objects-update
    ... objects-update code ...
  })(); // End objects-update
  ... gravity code ...
  (function() { // Start draw
    ... draw code ...
  })(); // End draw
  ... gravity code ...
})(); // End gravity

If you know the RIFFWAVE.js, you can see this method is good to include third part projects, but when the js lib provide features as "global" variables, by only declaring it on the root scope of the file, you must change a detail: remove the "var" before the variable declaration inside the module and declare it on the parent scope, as you see on the simplified code above.

This feature also helps the minifyer as I could see while implementing it. The closures allows the minifyer to reset the variable naming and this is also good for the zip algorithm.

An open issue: the first implementation does not supports modules that includes it ancestors, because that will enter in a infinite loop.


Another long term wanted feature is macros. A simple comment define a macro and that will be valid for the entry file, and for the included sub-modules. You define a macro like this:

//macro myConst: 123
//macro sum: ( parseFloat(@1) + parseFloat(@2) )
//macro size: ( @1.length || 0 )

Then you can use like this: = myConst * zoom + "px";
total = sum(, * 3;
for (var i=0; i<size(obj); i++) doSomething(obj[i]);

And the result will be: = 123 * zoom + "px";
total = ( parseFloat( + parseFloat( ) * 3;
for (var i=0; i<( obj.length || 0 ); i++) doSomething(obj[i]);

The parenthesis used on parametrized macros are not mandatory, but, as you can see on the second line of the usage example, the result is placed directly over the macro call without any "protection". In most cases were you define an expression in a macro you may need to protect it in a parenthesis to do not fight with toe operators precedence.

By this way, macros can extend js like this:

//macro forEach: for(var item,_i=0; item=@1[_i],typeof(item)!='undefined'; _i++)
var list = [123, false, 'hello', null, 'world'];
forEach(list) { console.log(item) }

That works nice, but doing this you don't have a valid javascript anymore. If you want sugar syntax you must consider other language that compiles to javascript, like CoffeeScript. (And i must to say: I love CoffeScript!)

How macros can help me?

If you don't use it for evil, that works pretty much like variables and functions. The first benefit is that you don't need to put parenthesis to your macro call if it does not requires parametrization and it still being some dynamic thing, different from a simple variable.

Macros are know for giving efficiency on C programs. Things goes faster when you don't need to allocate functions and other things in memory, but we can't handle the complexity without some abstraction feature, so you can try to put macros where you would put functions. But that is useful for javascript too? I always believe the answer is "yes", but surely the impact may not to be the same. So, i decide to test it. I implement some silly test to ensure this idea:

I did wrote this files: test.metajs and test.js, with exactly the same algorithm and data, but one with macros and the other with variables and functions.

Then i run this scripts in the browser ans in node.js, with this results:


  • Arithmetic with vars run 1000000000 times, in 35.315 seconds.
  • Arithmetic with literals run 1000000000 times, in 27.654 seconds.
  • Calling functions run 100000000 times, in 13.531 seconds.
  • Calling parametrized macros run 100000000 times, in 13.528 seconds.


  • Arithmetic with vars run 1000000000 times, in 13.677 seconds.
  • Arithmetic with literals run 1000000000 times, in 13.676 seconds.
  • Calling functions run 100000000 times, in 12.951 seconds.
  • Calling parametrized macros run 100000000 times, in 11.777 seconds.


  • Arithmetic with vars run 1000000000 times, in 39.675 seconds.
  • Arithmetic with literals run 1000000000 times, in 33.426 seconds.
  • Calling functions run 100000000 times, in 14.232 seconds.
  • Calling parametrized macros run 100000000 times, in 13.886 seconds.

The values vary on each running, but they do not change so much. When I see some big variation, it's something lower then 10%. So... in this silly test we see no important efficiency gain on using macros. This may be related to the compiler optimizations or to the nature of javascript. I don't know... Maybe there are some cases where macros will show its power, but i'm less interested in macros to efficiency, and more about the final size reduction.

Size reduction?

Well... That is obvious, if we are talking about the compiled code size, it depends on the macro/value length relation. But, if we are talking about the zip compressed final size, it's harder to answer, and to give a real example. So, i will only remember you about "data entropy". In some cases you have some steps repeating over and over in a module, like that all "ctx.bP() ... ctx.cP()" on my draw.metajs. You may have the same idea as i had: replace they with a abstraction function. I got a file with less chars, but the final zip file size grows up. I did try hard, the zip size floats, but never got smaller then the size without repeated steps. That happens because the data entropy. If you have big sub strings repeating N times, the compressor only need to point this as a "word" on each N instance. That is cheap. On the other hand, if you have small sub strings repeating N times, plus a new big string, you will need more or less the same space as before with more some space to this extra word (the abstraction function). You have less chars, but more information. That also happens with variables, which required more creativity to reduce the final size.

So, macros can (not ever, but often) reduce your code complexity and the entropy. We can't be sure before test, so a good feature for metajs compiler could be the parameterization of the macro replacement: that must works as a standard macro or must define a function? So you can test how it influence the zip's final size.


The metajs compiler is, today, a (not so much) simple BASH function hardly dependent on sed. Please, see the file. In that file we see the function generateJS with this steps:

  1. build a sed script, by searching for "//macro" definitions, and for each one write a replacer sed expression;
  2. print the closure start;
  3. print line by line of the macro replaced content;
  4. if the line contains "//include" , replace it by the generateJS processed content of the referenced file; (The generateJS recursive call also receives the current sed script, so macros from a ancestor module are valid inside descendants.)
  5. print the closure end.

Simple right? I don't know if that will have a future, but if it happens, the first step will be rewrite in javascript. Here is the project page:, if you have some idea or proposal, please, comment here or issue the project.


22 comentários

Enviar um comentário
  • B5f0eacce104eba5fc195600f8efdf39?only path=false&size=50&d=404RobfupOrery(usuário não autenticado)
    9 de Março de 2017, 7:50

    Metformin Online

    Achat Cialis Cheque How To Get Lasix Can You Buy Sildenafil Over The Counter Viagra Effet Secondaire Buy Cialis Citalopram Online Buy Cialis From Canada Cheapest Kamagra Online Clomid Acupuncture Ivf Bentyl Secure Ordering Online Viagra For Sale Priligy Meinungen Viagra Online Switzerland Cheap Generic Cialis Viagra Avec Ou Sans Ordonnance Amoxicillin Infection Brand Cialis Cialis Generico Esiste Commander Baclofen 10mg Levitra Brand Online Comprar Cialis En Madrid Isotretinoin Acne Deltasone Cost Tadalis Sx France Cephalexin Or Cefalexin Antabuse Online Fast Prednisone Canadian Pharmacy Achat Viagra Web Propecia Brand Viagra Efecto Prolongado Mexican Amoxicillin Cheap Cialis Can I Purchase Tab Secure Ordering Provera Shipped Ups Il Viagra Fa Male Al Cuore Kamagra Buy Online Propecia Generico Madrid Rx Cheap Propecia Buy Generic Cialis Levitra Ebay order accutane online from canada Cheap Generic Viagra Avodart Lowest Price Achat Kamagra Au Canada Xenical Cost Cialis Prezzo Migliore Viagra For Men Australia Cheap Price Buy Accutane Online Cheap Acheter Cialis Doctissimo Cephalexin Online With Next Day Shipping Buy Azithromycin Online Tadalafil 20 Mg For Sale Order Valtrex Online With No Prescription Comprar Priligy En Internet Foros Donde Comprar Viagra Cialis Generique Arnaque Order Cialis Viagra Online Rezeptfrei Propecia Causa Sterilita Kamagra Order Cytotec Et Maladie Propecia Canadian Drug Stores Antabuse Pill Acheter Cialis France Pharmacie Cialis 5mg Gunstig Kaufen Nolvadex Tamoxifen Safe Cialis Online Amoxil Dosage Pediatric Online Priligy Gunstig Cialis Vendo Kamagra Tenerife Buy Xenical Cheap Cialis Prix Au Maroc Levaquin 250mg In Internet Cheap Generic Zoloft Levitra Biglietti On Line

  • B5f0eacce104eba5fc195600f8efdf39?only path=false&size=50&d=404RobfupOrery(usuário não autenticado)
    30 de Março de 2017, 13:45

    Misoprostol Achat Ligne

    Macrobid Tablet For Sale cialis online pharmacy Cephalexin Liquid For Toddlers Cialis England online pharmacy Generic Progesterone Menopause Mastercard Accepted Price Online American Drugstore Online Inderal Free Offer Get 20 Viagra Levitra Quanto Tempo Prima Achat Clomid Pas Cher Maca Powder Cialis Y Presion Arterial Buy Cialis Prix Viagra Pharmacie Suisse Fish Amoxicillin Clavulanic Cheapest Amoxil Does Cialis Work Cialis 5 Mg Beipackzettel Buy Nolvadex Cheap Overnight Cialis Canada Buy Xenical Over The Counter Antabuse Buy Online Propecia Half 1 Mg Amoxil Chew Tabs Levitra Soft Tabs Comprar Viagra Espana Clomid Mal De Nombril Cost Of Amoxil Levitra Be Ordered In Usa Canadian Pharmacy Drugs Online Cheap Viagra Pill Nolvadex En Ligne Priligy Originale Online Order Propecia Where To Buy Pyridium Medication Cod Only Store Viagra Vendita Negozio Where Can I Buy Nolvadex Pct Buy Clomid And Nolvadex Online Kamagra Generika Online Bestellen Cost Of Propecia Buy Valtrex In Thailand Priligy Permanent Order Cheap Amoxil Difference Entre Cialis Et Generique

Enviar um comentário

* campo é obrigatório

Se você é um usuário registrado, pode se identificar e ser reconhecido automaticamente.