rsms / move

A simple, functional-biased, prototypal and powerful programming language that runs on any ES3 (or better) JavaScript platform, aimed toward people new to programming
306 stars 23 forks source link

Bug? Strange behaviour of 'while' #3

Closed holtwick closed 13 years ago

holtwick commented 13 years ago

The following executed with move 0.1.2 installed via 'npm' does not generate any output on my Mac OS 10.6 driven machine:

x = 10
while (x) {
    print "x =", x
    x -= 1
}

But this does:

x = 10
while (true) {
    print "x =", x
    x -= 1
    if(!x) break;
}
rsms commented 13 years ago

Wow, this is really interesting... The Move code you posted compiles to the following JS code (I've stripped away the runtime exports and replaced "print" otherwise pristine from the compiler):

(function(){"use strict";
  var x;
  x = 10;
  while (x) {
    console.log("x =", x);
    x -= 1;
  }
})();

When I run this as plain JS in Node.js it works. However, when I run your test case Move code (the first one that yielded no output) in Chromium, it works as expected. Try to run the test case in http://movelang.org/try/ and you should get the expected results. This leads me to believe we might have found a bug in Node.js or at least some undocumented or obscure feature/restriction of the native "vm" module used by Node.js (which is a wrapper around the V8 source execution API).

I'll investigate.

rsms commented 13 years ago

I found the bug faster than I expected — the bug is actually in UglifyJS and occur when applying optimizations. This is the actual generated code when used as a Node.js module:

(function(){"use strict";
  var x;
  x = 10;
})();

UglifyJS "optimized away" the while loop. I'll file a bug report.

rsms commented 13 years ago

Merged in some patches and fixes made in upstream UglifyJS which closed by b825eda903547892a2f742ef2c574cac9d45c6c3

holtwick commented 13 years ago

I did not yet dive into the Move code to deep, but I guess move does not depend on UglifyJS? If so I would suggest to be more 'conservative' and turn optimizations off by default. Else it is just another trap to fall into while debugging ;)

rsms commented 13 years ago

The Move parser and codegen is based on UglifyJS. The level of modification is so "severe" though that patching in things done in upstream has to be done line for line, change for change by hand. A pain, simply put. UglifyJS is an awesome project but the code base lives up to the name — it's not very modular (which is both a feature of its design and a flaw) for starters.

Optimizations can be turned on/off or increased by passing an integer in the range [0-2] for "optimizationLevel" to the move.compile function. The Node.js module hook-in stuff that has that flag set to 1 by default. Maybe the winnings are so small we can disable optimizations.

holtwick commented 13 years ago

Ok, this really sounds like pain. I think a more solid approach would save a lot of troubles for the future.

From my studies at the university I learned that a language grammar e.g. defined in (E)BNF is a good starting point and gives a good overview over the structure of the language. These grammar definitions can be put into a parser generator like one of these http://en.wikipedia.org/wiki/Comparison_of_parser_generators The rest will be easier since most tokens can be written back into code in our case.

The hard part is to find something suitable for this written in Javascript and to find a Javascript grammar as a starting point. Performance should be secondary and could be added when everything is stable. This link might help: http://stackoverflow.com/questions/1823612/lexer-written-in-javascript

If you want to do it from the ground, I can recommend this old book. I wrote my compiler with it in the 80ies or 90ies ;) http://www-old.oberon.ethz.ch/WirthPubl/CBEAll.pdf