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

2008-07-29 Thread Ingvar von Schoultz
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
u

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

2008-07-29 Thread Ingvar von Schoultz
I'd like to summarize some clarifications and arguments.

I'm thinking of what it might be like if {{ }} should become
available in ES3.1.



=== Intuitive ===

The proposed {{ }} mean exactly the same thing as { } in C, Java etc.

If switching between languages causes you any difficulties, simply
use {{ }} everywhere in your ES3.1 code. This way you get the braces
that you're used to from C and Java, apart from a slightly different
notation.

Think of it as JavaScript having a small difference in brace notation
while the functionality is the same.



=== Control flow ===

In ES3 you can use { } for plain control flow, without any scoping.
This is very useful for small projects.

If this is not a good fit for your projects, it's still very useful
elsewhere. Please don't deprecate this functionality.

For more on the usefulness of this plain control flow, see:
https://mail.mozilla.org/pipermail/es4-discuss/2008-July/003353.html



=== Difference ===

If you want the full flexibility of using both {{ }} and { },
first decide which type of brace you want to use most in your
program. Stick with that almost everywhere. Make an exception
only when you have a clear and specific reason, because you
need the functionality of the other type.

This way your code will be consistent and readable.

You can view the {{ }} as containers for variables. Any variable
that you declare anywhere will simply splash out of any { } and
attach itself to the nearest surrounding {{ }}, becoming visible
in the entire space between them.

If you prefer a more low-level view, { } are plain jumps and
branches, and only {{ }} affect the scope chain.



=== Ugly ===

The proposed {{ }} will inevitably look horrible in emails if
you use a proportional font such as Times New Roman. Real code
is never displayed in such a font. Try a programmer's editor
with a suitable font and syntax coloring. It looks completely
different!

If people still find it ugly, I hope a good alternative can be
found, because the functionality would be very useful.



=== Let declarations ===

There are existing implementations that support let.

My proposal is that /let declarations/ should be completely disabled
between {{ }}. This of course includes all { } that are nested between
{{ }}.

The only reason is simplicity, mainly for the script programmer.

Outside {{ }} they should be enabled, for compatibility and to satisfy
those who prefer the let and var combination.



-- 
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.)
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


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

2008-07-29 Thread Ingvar von Schoultz
If the simple translation of {{ }} is used, any governing
for(), while() or switch() must be moved inside the scoping
function.

A very simple, very minimalistic approach may be enough.

 for (var Name in Thing)
 {{
 }}

Name is locally contained inside {{ }} while Thing is outside.
But maybe the compiler doesn't have to make this distinction.

Personally I'd never use the same name with different meanings
so close together, like this:

 var Thing = ...;
 for (var Name in Thing)
 {{  var Thing = ...;
 }}

I find that obscure and error-prone.

If the limitation is acceptable, a very minimalistic translation
of {{ }} could simply move the entire for (...) inside the
scoping function, and leave it at that. As long as Thing isn't
redeclared inside, the outer Thing is visible and it works.

Does this make it simple enough for ES3.1?

As an added bonus, the functionality becomes very easy to explain.
The rules become very plain and simple.

I don't know if a let statement with this limitation would be
useful. Every description of let that I can find re-uses names.
But if it's useful, it could be trivially implemented as syntax
sugar:

 let (a = x, b = y)
 {{
 }}

would be syntax sugar for

 {{  var a = x, b = y;
 }}

However "let" has different semantics in at least one existing
implementation (it does distinguish between same-name variables
in the two scopes), so if a minimalistic let is introduced, it
should probably use a different keyword.

-- 
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.)
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


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

2008-07-29 Thread Ingvar von Schoultz
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.)

___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: Questions about setters

2008-07-29 Thread Brendan Eich
On Jul 29, 2008, at 7:53 AM, P T Withington wrote:

>> In AS3 it's like this:
>>
>> override function set bar (value) {
>> super.bar = value;
>> }
>
> So, can I say:
>
> override function set * (id, value) {

There's no such syntax in ES4 as proposed -- the last grammar sent  
out does not produce * after set in FunctionDefinition^class.

The proposal was meta function set(id, value) {...}, and as far as I  
can see in that proposal, super[id] should work.

/be

>note('setting ' + id + ' to ' + value);
>super[id] = value;
> }
>
> ?  (It seems currently, AS3 does not allow `super[]`?)
> ___
> Es4-discuss mailing list
> Es4-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es4-discuss

___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: Questions about setters

2008-07-29 Thread P T Withington
On 2008-07-25, at 05:52EDT, Peter Hall wrote:

>> Not sure, but there might be something in the super syntax (eg,  
>> "super.x
>> = 10") that
>> would do this.  Hasn't been spec'd yet.  Not sure what AS3 does.
>>
>
>
> In AS3 it's like this:
>
> override function set bar (value) {
> super.bar = value;
> }

So, can I say:

override function set * (id, value) {
   note('setting ' + id + ' to ' + value);
   super[id] = value;
}

?  (It seems currently, AS3 does not allow `super[]`?)
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: How to escape implicit 'with (this)' of a method body

2008-07-29 Thread P T Withington
On 2008-07-29, at 01:19EDT, Brendan Eich wrote:

> On Jul 28, 2008, at 10:05 PM, Jon Zeppieri wrote:
>
> The original code used "without (this)", not "with", which I took to  
> mean "avoid instance properties shadowing globals".

Indeed.  Perhaps I was being too clever in my pseudo-code.

> If you read the original as "with", then there is no such problem.  
> But if you construct a problematic case using 'with' and dynamic  
> properties, then I concede that 'global' could be shadowed. This is  
> a reason to avoid 'with'. In the ES4 proposals last sent out, you  
> could always use __ES4__::global if you really wanted to avoid  
> conflicts -- unless someone perversely added '__ES4__' as a dynamic  
> instance property.
>
> There's no solution to this problem other than reserving at least  
> one name, and we can't do that compatibly. We could reserve __ES4__  
> in version-selected ES4 mode, but that seems unnecessary.

I guess this is considered a small penalty to pay in exchange for  
adding the magical instance scope to methods (which O-O programmers  
seem to expect these days).  Something we'd regret more if we had  
multi-methods, perhaps...
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Defaulting parameters to previous arguments

2008-07-29 Thread P T Withington
Will es4 let me say this?

   function select (start:Number, end:Number=start) { ... }

or do I have to resort to something like:

   function select (start:Number, end:Numer=null) {
 if (end == null) { end = start; }
 ...
   }
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: How to escape implicit 'with (this)' of a method body

2008-07-29 Thread P T Withington
On 2008-07-28, at 18:22EDT, Michael Haufe wrote:

> /function foo () { return 'global'; }
>
> class bar {
>  function foo () { return 'local'; }
>
>  function zot () {
>// How can I call the global foo from here?
>without (this) { foo(); }
>  }
> }/
>
> You could use window["foo"](); or whatever the global object is  
> named in the environment

Shouldn't there be an es4 standard way of doing it, without relying on  
a particular environment?

class bar {
  function foo () { return 'local'; }

  // I guess this should work, but it seems rather kludgey
  static function globalfoo (...) { return foo(...); }
  function zot () {
globalfoo();
}
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss