A simple translation of the scoping-block syntax sugar -- Was: Re: function hoisting like var

Ingvar von Schoultz ingvar-v-s at comhem.se
Tue Jul 29 17:17:12 PDT 2008


The translation can be made simpler.

First, define a unique value, to be returned when the end of
the scoping block is reached. If done in JavaScript:

     var _EndOfBlock = {};

Then each {{ }} can be translated to this:

     var _ReturnValue = (function (arguments)
     {
         // Any governing for(), while() or switch() goes here.
         {
             // The code between {{ }} goes here.
         }
         return _EndOfBlock;
     }).call (this, arguments);
     if (_ReturnValue != _EndOfBlock)
         return _ReturnValue;

Ingvar



Ingvar von Schoultz wrote:
> The simple translation of {{ }} that I posted yesterday needs
> an improvement. It must pass |this| and |arguments| to the scoping
> function.
> 
> I still think it looks quite small and simple, and that it would
> be a very useful addition to the language.
> 
>      try
>      {   var _ReturnValue = (function (arguments)
>          {
>              // Any governing for(), while() or switch() goes here.
>              {
>                  // The code between {{ }} goes here.
>              }
>              throw _NormalEndSignal;
>          }).call (this, arguments);
>          return _ReturnValue;
>      }
>      catch (_Sig)
>      {
>          if (_Sig != _NormalEndSignal)
>              throw _Sig;
>      }
> 
> We must use .call(), not .apply(), so that we pass the arguments
> object as such, with the outer function as arguments.callee.
> 
> In the global scope, |arguments| will be undefined, unless the
> programmer has defined it. It should remain undefined inside the
> scoping function.
> 
> As an alternative to the above parameter passing, I suppose the
> implementation can simply remove the scope function's arguments
> object, thereby making the outer arguments object visible.
> 
> Initial underscore means hidden, invisible.
> 
> For a description of the translation, see the quoted text below.
> 
> Ingvar
> 
> 
> 
> Ingvar von Schoultz wrote:
>> Ingvar von Schoultz wrote:
>>> In theory {{ code }} could be converted to a function that
>>> returns information about whatever break/continue/return was
>>> reached.
>> I now think this could be made very simple.
>>
>> The solution is to make this version slightly limited. Don't
>> support break/continue statements that mention any label
>> outside {{ }}. Leave that for a future version.
>>
>> This simplifies things tremendously! And you don't need that
>> kind of break/continue all that often. (But a future version
>> must include it.)
>>
>> This limited solution only needs break/continue functionality
>> that is already supported. Even the necessary label checking
>> is already supported. An unsupported break such as the following
>> gives a syntax error if you translate {{ }} to a one-shot
>> function:
>>
>>      Outer:
>>      for (var OutName in OutThing)
>>          for (var InName in InThing)
>>          {{
>>              break Outer;
>>          }}
>>
>> The error message that I get says "undefined label", which
>> is misleading, but apart from that it works perfectly.
>>
>> If people find the above limited support for break/continue
>> acceptable for this version, all that remains is the return
>> statement.
>>
>> It seems easiest to use a solution that leaves all the return
>> statements in the original code intact. This makes the translation
>> from {{ }} to function a little elaborate and odd, but everything
>> is nicely contained at one spot.
>>
>> Within the created function, if control reaches the final }},
>> throw a special error that isn't really an error, rather the
>> opposite, it's a signal that indicates that this is a normal
>> termination. When this signal is received, continue below }}.
>>
>> If instead, within the created function, control reaches a
>> return statement that appears in the original code, the result
>> is a regular return, without the above thrown signal. This
>> indicates that whatever value was returned should be passed
>> along as return value of the enclosing function.
>>
>> This means that {{ }} is essentially translated into this:
>>
>>      try
>>      {   var ReturnValue = (function()
>>          {   // The code that was written between {{ }} goes here.
>>              throw NormalEndSignal;
>>          })();
>>          return ReturnValue;
>>      }
>>      catch (Sig)
>>      {   if (Sig != NormalEndSignal)
>>              throw Sig;
>>      }
>>
>> It seems to me that this becomes very nicely contained,
>> very manageable.
>>
>> Implementations will probably want to optimize away this
>> entire elaborate arrangement and replace it with plain and
>> simple scoping blocks. But they can take their time. The
>> above provides the functionality in a simple way.
>>
>> That is, unless I've missed something, and the above solution
>> doesn't work the way I think it does.
>>
> 

-- 
Ingvar von Schoultz

------- (My quirky use of capitals in code comes from my opinion that
reserved and predefined words should all start with lowercase, and
user-defined should all start with uppercase, because this will easily
and elegantly prevent a host of name-collision problems when things
like programming languages are upgraded with new labels.)



More information about the Es4-discuss mailing list