Re: function hoisting like var

2008-07-28 Thread Ingvar von Schoultz
Ingvar von Schoultz wrote:
 In theory {{ code }} could be converted to a function that
 returns information about whatever break/continue/return was
 reached. But I'd be quite surprised if that is easy.
 
 Something like this. Written with syntax sugar:
 
  Outer:
  for (var OutName in OutThing)
  for (var InName in InThing)
  {{
  break Outer;
  }}
 
 Translation:
 
  Outer:
  for (var OutName in OutThing)
  {
  var _Result = (function (_InThing)
  {
  for (var InName in _InThing)
  {
  return ({JumpSpot: 'break Outer'})
  }
  })(InThing);
  if (_Result.JumpSpot == 'break Outer')
  break Outer;
  }
 
 The inner for() is part of the scoping block, so it belongs
 inside, even though the original code has it above.
 
 We must make sure the value of InThing is available inside
 even if the name is declared for a different variable inside.
 
 I use initial underscore to indicate something internal and
 invisible.
 
 It doesn't look complicated here! Unfortunately these things
 have a terrible tendency to grow in complexity...

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


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

2008-07-28 Thread Michael Haufe

/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
___
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-28 Thread Brendan Eich

On Jul 28, 2008, at 3:22 PM, 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(); }
   }
}


It's the same as if you lambda-coded the above (here shown in JS1.8  
[Firefox 3], note the expression closures):


function bar() {
  function foo() 'local';
  function zot() global.foo();
}
function foo() 'global';

This example uses ES4's global synonym for the global object, but you  
could capture this in a global var at top level:


var global = this;
print(new bar().zot()); // print 'global'

in ES3 or JS1.8 to get the same effect.

You could use window[foo](); or whatever the global object is  
named in the environment


No need to quote and bracket, of course -- window.foo() is fine too.

/be

___
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-28 Thread Brendan Eich

On Jul 28, 2008, at 9:46 PM, Brendan Eich wrote:


On Jul 28, 2008, at 3:22 PM, 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(); }
   }
}


It's the same as if you lambda-coded the above (here shown in JS1.8  
[Firefox 3], note the expression closures):


function bar() {
  function foo() 'local';
  function zot() global.foo();


+  return {foo: foo, zot: zot};


}
function foo() 'global';

This example uses ES4's global synonym for the global object, but  
you could capture this in a global var at top level:


var global = this;
print(new bar().zot()); // print 'global'

in ES3 or JS1.8 to get the same effect.


/be___
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-28 Thread Jon Zeppieri
2008/7/29 Brendan Eich [EMAIL PROTECTED]:
 On Jul 28, 2008, at 3:22 PM, 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(); }
}
 }

 It's the same as if you lambda-coded the above (here shown in JS1.8 [Firefox
 3], note the expression closures):
 function bar() {
   function foo() 'local';
   function zot() global.foo();
 }
 function foo() 'global';
 This example uses ES4's global synonym for the global object, but you could
 capture this in a global var at top level:
 var global = this;
 print(new bar().zot()); // print 'global'
 in ES3 or JS1.8 to get the same effect.

 You could use window[foo](); or whatever the global object is named in the
 environment

 No need to quote and bracket, of course -- window.foo() is fine too.
 /be

Isn't the 'with' statement in the original example significant?  In
the general case, assuming that you don't know what properties 'this'
has (as it may have dynamic properties in addition to the fixtures
determined by its class), you have no way of knowing whether 'global'
or 'window' refers to the global object or to some arbitrary property
of 'this.'

-Jon



 ___
 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: How to escape implicit 'with (this)' of a method body

2008-07-28 Thread Brendan Eich
On Jul 28, 2008, at 10:05 PM, Jon Zeppieri wrote:

 Isn't the 'with' statement in the original example significant?  In
 the general case, assuming that you don't know what properties 'this'
 has (as it may have dynamic properties in addition to the fixtures
 determined by its class), you have no way of knowing whether 'global'
 or 'window' refers to the global object or to some arbitrary property
 of 'this.'

The original code used without (this), not with, which I took to  
mean avoid instance properties shadowing globals. 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.

/be

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