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 11:30:58 PDT 2008
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