code-dot-org/blockly-core — pull request #90 by cpirich (2014-05-27 20:22:48+00:00)
Title: [#70326328]: add support for local variables with varsInGlobals mode

The recent varsInGlobals change is working well, except in one important case: parameters when you create functions. The function generated would look like this: Globals.foo = function (param1) { return Globals.param1; };

The key issue is that blockly-core doesn't really differentiate global variables from local variables. All variables appear in the Variables category in the toolbox (including function parameters) and are typically declared as global variables as 'var param1;' at the top of the generated code. Strangely, function params exist in the local scope and the global scope simultaneously (with different values for each).

With the recent varsInGlobals change, the code generated (as displayed above) was completely broken. So while I couldn't muster the courage to try to fix the overall globals/locals problem (which requires a serious design discussion), I did decide to tackle the new problem that broke functions for studio.

Blockly maintains a database of all variables and function names (called variableDB_). It has a simple notion of type for each name entity (variable vs. function). This database is an instance of the Blockly.Names class. I enhanced the BlocklyNames class to optionally store a specificType in addition to the existing type. This way, when a local variable is first added to the database, it can store both the type (variable) and specificType (local variable). Then when any block generates code later, it can check for the specificType to determine whether or not it should emit a global variable reference (Globals.i) or a local variable reference (i).

I created a translateVarName() helper function that encapsulates this logic. In a few tricky places, the JavaScript generator still needs access to the "undecorated" name - for creating temporary local variables.

I also had to slightly re-order some code to ensure that the first reference to the Blockly.Names instance for function parameters was from the code that generates the function body.

None of these changes should impact the generated code when varsInGlobals is not set.

I inspected the generated code for the varsInGlobals case (studio only for now) and tested lots of new blocks there in studio level 100 (aka #8).

I ran all of our blockly apps grunt tests and everything passes.