Promises, the middle state : negociation
Hi all, As I totally agree that a promise can only be resolved or rejected once ... so I think his behavior is perhaps too black or white. As IRL, when we receive a promise, we expect that the author makes every effort to resolve it, by any way. Progammatically, we can wish the same. By example, we can have : - an error to ignore - an error that requires to execute other operations leading to - a rejection - a continuation - a retry To cover all these cases, in the current promises state, we can have (a quite) complex promises, easily solvable. My idea? the negociation, where the goal is to find a solution to resolve it (rejection reduction). For the promise fn argument, to add an optional negociate argument. ``` promise = new Promise(function (resolve, reject, negociate) { // the promise body }); ``` An the related Promise.negociate method like : ``` Promise.negociate = function negociate(resolve, reject, negociate, retry, value) { }; ``` That returns a promise, negociable too, where : - resolve is shared with the original promise (that contains the negociate call) to continue the process - reject is shared with the original promise (that contains the negociatecall) - negociate, it's own negociation, for multiple attempts/behaviors - retry to recall the original promise fn argument (compliant with the promises concept, since our promise was neither rejected nor resolved, at this point) - value (or values, I'm not sure) to pass some infos/tools that we need to take our decision, in the negociation process Lemme your advices. ;) Michaël Rouges - https://github.com/Lcfvs - @Lcfvs ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Assignment to method invocation result
Throughout my history with JS (and pretty much every programming language I've used) I've always found one thing really awkward: reassigning a variable to the result of its method. Say you have code like this: var foo = function (options) { var string = something(); if ( options.stripWhiteSpace ) { string = string.trim(); } // do something else here... }; The same thing applies to pretty much all methods that return a modified version of the same type of the variable, e.g. replace, filter, map, concat, etc., you name it. As a comparison let's say we had Number#add() and no operators for the add method: var bar = function (firstNumber, secondNumber) { var thirdNumber = 5; if ( firstNumber 0 ) { secondNumber = secondNumber.add(thirdNumber); } firstNumber = firstNumber.add(secondNumber); }; whereas with the operators we have the convenience of combining the operator with the assignment to avoid typing the variable name twice: var bar = function (firstNumber, secondNumber) { var thirdNumber = 5; if ( firstNumber 0 ) { secondNumber += thirdNumber; } firstNumber += secondNumber; }; I don't really know what would be a good solution for this problem, hence I wanted to share this here if we can figure out a nicer way to do these kinds of things. The best I can think of is some syntax like this: var foo = function (options) { var string = something(); if ( options.stripWhiteSpace ) { string = .trim(); } // do something else here... }; so basically the operator would a combination of assignment followed by property access dot, then the method name and invocation. This could also allow plain property access so you could for example say `foo = .first` or something. The reason I don't like this syntax is that it might be conflicting with other some ideas thrown around to replace `with`, e.g.: using (foo) { .remove(x); var x = .size; } - Jussi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: bugs.ecmascript.org problem?
I'm still experiencing the problem, having just, in the same operation, put myself on the CC list and added a comment on some bug. Therefore I've open a new bug for that issue, see Bug 2868: https://bugs.ecmascript.org/show_bug.cgi?id=2868 (Naturally, the issue was observed again when created that bug.) —Claude Le 29 avr. 2014 à 08:42, Claude Pache claude.pa...@gmail.com a écrit : Just entered a bug, experiencing the same symptom. —Claude Le 29 avr. 2014 à 00:40, Michael Dyck jmd...@ibiblio.org a écrit : For the past couple of days, when I create or modify a bug on bugs.ecmascript.org, my browser doesn't get a response. I know the requests are being received, because when I check via another tab, the creation or modification has happened. (I *do* get a response for all my other requests.) Is anyone else seeing this? -Michael ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: bugs.ecmascript.org problem?
On Tue, Apr 29, 2014 at 12:40 AM, Michael Dyck jmd...@ibiblio.org wrote: For the past couple of days, when I create or modify a bug on bugs.ecmascript.org, my browser doesn't get a response. I know the requests are being received, because when I check via another tab, the creation or modification has happened. (I *do* get a response for all my other requests.) Is anyone else seeing this? Maybe it's an idea to just get a component here: http://www.w3.org/Bugs/ That could be easily arranged. -- http://annevankesteren.nl/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promises, the middle state : negociation
On Thu, May 15, 2014 at 11:33 AM, Michaël Rouges michael.rou...@gmail.com wrote: Hi all, As I totally agree that a promise can only be resolved or rejected once ... so I think his behavior is perhaps too black or white. As IRL, when we receive a promise, we expect that the author makes every effort to resolve it, by any way. Progammatically, we can wish the same. By example, we can have : an error to ignore an error that requires to execute other operations leading to a rejection a continuation a retry To cover all these cases, in the current promises state, we can have (a quite) complex promises, easily solvable. My idea? the negociation, where the goal is to find a solution to resolve it (rejection reduction). For the promise fn argument, to add an optional negociate argument. ``` promise = new Promise(function (resolve, reject, negociate) { // the promise body }); ``` An the related Promise.negociate method like : ``` Promise.negociate = function negociate(resolve, reject, negociate, retry, value) { }; ``` That returns a promise, negociable too, where : resolve is shared with the original promise (that contains the negociate call) to continue the process reject is shared with the original promise (that contains the negociate call) negociate, it's own negociation, for multiple attempts/behaviors retry to recall the original promise fn argument (compliant with the promises concept, since our promise was neither rejected nor resolved, at this point) value (or values, I'm not sure) to pass some infos/tools that we need to take our decision, in the negociation process Lemme your advices. ;) This is just normal promise chaining. If you get a promise and want to make *sure* it resolves in a particular way, just use .then() or .catch() to create a new promise that handles things the way you want. ~TJ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Promises, the middle state : negociation
I don't pretend that impossible to do with current promises. I'm just saying that we can get a complexity that could be easily avoided. And a catch/then doesn't allow to return in the first promise onFulfilled, without embedded promises. I think a practical example might better illustrate the thing. Imagine, we have to check a data integrity, firstly internal, or from external sources, if the internal data is corrupted. The integrity controller is a foreign promisable controller , with a custom hash method a fingerprint... we can't touch it. ``` var foreignController; foreignController = (function () { var fingerPrint, hash, controller; fingerPrint = 'aforeignfingerprint'; hash = function hash(data) { // foreign ownmade hash calculator }; controller = function controller(resolve, reject, negociate) { var data, isValid, sources; data = this.data; isValid = fingerPrint === hash(data); if (isValid) { return resolve(data); } sources = this.sources; if (sources.length) { // not an error, we only remove that source // and try with the next one return negociate(sources.shift()); } reject(new Error('No valid data found')); }; return controller; }()); ``` Now, the data ownmade data checker : ``` var getDataSync, onFulFilled, onRejected, onNegociated, handler, controller; getDataSync function getDataSync(source) { // data collector }; onFulFilled = function onFulFilled(value) { // valid data treatment }; onRejected = function onRejected(reason) { // no valid data found }; onNegociated = function onNegociated(resolve, reject, negociate, retry, value) { var source; source = this.sources[0]; this.data = getDataSync(source); console.log('data source corrupted : ' + value); retry(); }; handler = { data: 'some data', sources: ['internal', 'an.external.url', 'another.external.url', '...'] }; controller = foreignController.bind(handler); new Promise(controller) .then(onFulFilled, onRejected, onNegociated.bind(handler)) /* a lot of thens */; ``` Personnaly, I don't see how the current promises can solve it as simply. Michaël Rouges - https://github.com/Lcfvs - @Lcfvs ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Promises, the middle state : negociation
``` var sources = [internal, external1, external2]; function doStuff (e) { // likely check if it's the right kind of error; var url = sources.shift(); if (typeof url === 'undefined) { return Promise.reject(new Error('out of sources')); } return get(url).then(check).catch(doStuff); } ``` On Thu, May 15, 2014 at 10:52 AM, Michaël Rouges michael.rou...@gmail.comwrote: I don't pretend that impossible to do with current promises. I'm just saying that we can get a complexity that could be easily avoided. And a catch/then doesn't allow to return in the first promise onFulfilled, without embedded promises. I think a practical example might better illustrate the thing. Imagine, we have to check a data integrity, firstly internal, or from external sources, if the internal data is corrupted. The integrity controller is a foreign promisable controller , with a custom hash method a fingerprint... we can't touch it. ``` var foreignController; foreignController = (function () { var fingerPrint, hash, controller; fingerPrint = 'aforeignfingerprint'; hash = function hash(data) { // foreign ownmade hash calculator }; controller = function controller(resolve, reject, negociate) { var data, isValid, sources; data = this.data; isValid = fingerPrint === hash(data); if (isValid) { return resolve(data); } sources = this.sources; if (sources.length) { // not an error, we only remove that source // and try with the next one return negociate(sources.shift()); } reject(new Error('No valid data found')); }; return controller; }()); ``` Now, the data ownmade data checker : ``` var getDataSync, onFulFilled, onRejected, onNegociated, handler, controller; getDataSync function getDataSync(source) { // data collector }; onFulFilled = function onFulFilled(value) { // valid data treatment }; onRejected = function onRejected(reason) { // no valid data found }; onNegociated = function onNegociated(resolve, reject, negociate, retry, value) { var source; source = this.sources[0]; this.data = getDataSync(source); console.log('data source corrupted : ' + value); retry(); }; handler = { data: 'some data', sources: ['internal', 'an.external.url', 'another.external.url', '...'] }; controller = foreignController.bind(handler); new Promise(controller) .then(onFulFilled, onRejected, onNegociated.bind(handler)) /* a lot of thens */; ``` Personnaly, I don't see how the current promises can solve it as simply. Michaël Rouges - https://github.com/Lcfvs - @Lcfvs ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- -Calvin W. Metcalf ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Question regarding precision of Math functions
Hi everyone! It's interesting to me that many Math functions do not specify any bound on precision, even though it's possible to have some bounds (like Java does) or to even specify the algorithm since free ones exist (fdlibm being the one I'm familiar with). I am curious if this has been brought up before (quick and dirty search found nothing for me) and if there is some reason for not having a tighter spec, beyond lack of a champion. -Filip ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Assignment to method invocation result
On Thu, May 15, 2014 at 7:27 AM, Jussi Kalliokoski jussi.kallioko...@gmail.com wrote: Throughout my history with JS (and pretty much every programming language I've used) I've always found one thing really awkward: reassigning a variable to the result of its method. Say you have code like this: var foo = function (options) { var string = something(); if ( options.stripWhiteSpace ) { string = string.trim(); } // do something else here... }; The same thing applies to pretty much all methods that return a modified version of the same type of the variable, e.g. replace, filter, map, concat, etc., you name it. As a comparison let's say we had Number#add() and no operators for the add method: var bar = function (firstNumber, secondNumber) { var thirdNumber = 5; if ( firstNumber 0 ) { secondNumber = secondNumber.add(thirdNumber); } firstNumber = firstNumber.add(secondNumber); }; whereas with the operators we have the convenience of combining the operator with the assignment to avoid typing the variable name twice: var bar = function (firstNumber, secondNumber) { var thirdNumber = 5; if ( firstNumber 0 ) { secondNumber += thirdNumber; } firstNumber += secondNumber; }; I don't really know what would be a good solution for this problem, hence I wanted to share this here if we can figure out a nicer way to do these kinds of things. The best I can think of is some syntax like this: var foo = function (options) { var string = something(); if ( options.stripWhiteSpace ) { string = .trim(); } // do something else here... }; so basically the operator would a combination of assignment followed by property access dot, then the method name and invocation. This could also allow plain property access so you could for example say `foo = .first` or something. The reason I don't like this syntax is that it might be conflicting with other some ideas thrown around to replace `with`, e.g.: using (foo) { .remove(x); var x = .size; } This particular syntax would also require static (a lookahead) and semantic (based on the lookahead results) disambiguation to account for DecimalLiteral: var n = .2; If the . was on the other side? AccessorAssignmentOperator : .= IdentifierName var string = a ; string .= trim(); // would throw if no `trim` method existed for `string` string; // a; Where .= means assign the result of Property Accessors Runtime Semantics Evaluation with lval and rval in appropriate positions (TBH, I'm sure I missed something in there) Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Assignment to method invocation result
and what about obj []= 'propertyName' as well? --scott ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Assignment to method invocation result
On Thu, May 15, 2014 at 2:27 PM, C. Scott Ananian ecmascr...@cscott.netwrote: and what about obj []= 'propertyName' as well? --scott I imagined .= would do both, but I don't think my suggestion should be taken seriously. In fact, your example illustrates a major flaw (that exists in either proposal/suggestion), that I don't immediately know how I would answer: var o = { foo: bar }; o .= foo; Is `o` now a string with the value bar?? I think that would cause more problems than its worth. Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: bugs.ecmascript.org problem?
I've have a serve respect pending with Mozilla IT. I'll see if I can nudge them. Allen On May 15, 2014, at 4:58 AM, Anne van Kesteren wrote: On Tue, Apr 29, 2014 at 12:40 AM, Michael Dyck jmd...@ibiblio.org wrote: For the past couple of days, when I create or modify a bug on bugs.ecmascript.org, my browser doesn't get a response. I know the requests are being received, because when I check via another tab, the creation or modification has happened. (I *do* get a response for all my other requests.) Is anyone else seeing this? Maybe it's an idea to just get a component here: http://www.w3.org/Bugs/ That could be easily arranged. -- http://annevankesteren.nl/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bytecode
It's my understanding that the vast majority of the CLR's dynamic language support is at the runtime level, not the bytecode level. The bytecode is strongly typed (with lots of instructions/mechanisms for boxing, unboxing and type casts), and dynamic support is done through something called the 'DLR' that sits on top of the CLR. The DLR provides machinery for things like late binding and inline caches. For this C# snippet: ``` using System; public static class Program { public static void Main (string[] args) { dynamic one = (Funcint)( () = 1 ); dynamic doubleInt = (Funcint, int)( (int x) = x * 2 ); Console.WriteLine({0} {1}, one(), doubleInt(1)); } } ``` The desugared (well, decompiled from IL - the arg_XXX_X variables are from the decompiler, not actually in the IL) C# looks like this: ``` public static void Main(string[] args) { object one = () = 1; object doubleInt = (int x) = x * 2; if (Program.Maino__SiteContainer0.p__Site1 == null) { Program.Maino__SiteContainer0.p__Site1 = CallSiteActionCallSite, Type, string, object, object.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, WriteLine, null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } ActionCallSite, Type, string, object, object arg_15C_0 = Program.Maino__SiteContainer0.p__Site1.Target; CallSite arg_15C_1 = Program.Maino__SiteContainer0.p__Site1; Type arg_15C_2 = typeof(Console); string arg_15C_3 = {0} {1}; if (Program.Maino__SiteContainer0.p__Site2 == null) { Program.Maino__SiteContainer0.p__Site2 = CallSiteFuncCallSite, object, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } object arg_15C_4 = Program.Maino__SiteContainer0.p__Site2.Target(Program.Maino__SiteContainer0.p__Site2, one); if (Program.Maino__SiteContainer0.p__Site3 == null) { Program.Maino__SiteContainer0.p__Site3 = CallSiteFuncCallSite, object, int, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) })); } arg_15C_0(arg_15C_1, arg_15C_2, arg_15C_3, arg_15C_4, Program.Maino__SiteContainer0.p__Site3.Target(Program.Maino__SiteContainer0.p__Site3, doubleInt, 1)); } ``` So you can see all the inline cache and binding machinery at work there. As far as I know there were 0 bytecode changes to introduce this feature; I certainly didn't have to implement any special bytecodes to support 'dynamic' in JSIL. There are certainly some aspects of the CLR bytecode that make dynamic languages easier/harder to build on top of it, though. I just don't know what they are. I know a lot of the pain was reduced with the addition of 'lightweight code generation' or LCG, which allows jitting a single method on the fly and attaching it to a given context (like a method) so that it can access private members. This is used heavily in dynamic languages on the CLR now. On Wed, May 14, 2014 at 10:54 PM, C. Scott Ananian ecmascr...@cscott.net wrote: On Wed, May 14, 2014 at 9:12 PM, Axel Rauschmayer a...@rauschma.de wrote: It'd be great if there was material on the limits of the JVM and the CLR. AFAICT these are the only virtual machines that are trying to be universal (run both static and dynamic languages well). Well, from experience, the JVM is/was handicapped by some incidental decisions in its original standard library[*] that have a large adverse impact on startup time. This has restricted the 'usefulness' of the JVM from its inception. There are projects to re-engineer the standard library around this, but they have been slow (and are not yet complete)[**]. Similarly, the support for dynamic languages is fairly recent (JDK 7, JavaScript implementation using these features in JDK 8), so it's a bit early to know how that will play out in terms of adoption and practical use. So I'm not sure how much you're going to learn from the JVM, other than no matter how good/bad your bytecode is, other factors may dominate. That is: I would doubt most conclusions about bytecodes drawn from the example of the JVM, since I don't believe the bytecode design was a first order effect on its trajectory to date.
Re: Bytecode
maybe relevant to this topic: https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/ WebKit chaps basically transform JS to LLVM compatible instructions Too bad they are testing from 2007 libraries such Prototype and inheritance.js :P On Thu, May 15, 2014 at 8:14 PM, K. Gadd k...@luminance.org wrote: It's my understanding that the vast majority of the CLR's dynamic language support is at the runtime level, not the bytecode level. The bytecode is strongly typed (with lots of instructions/mechanisms for boxing, unboxing and type casts), and dynamic support is done through something called the 'DLR' that sits on top of the CLR. The DLR provides machinery for things like late binding and inline caches. For this C# snippet: ``` using System; public static class Program { public static void Main (string[] args) { dynamic one = (Funcint)( () = 1 ); dynamic doubleInt = (Funcint, int)( (int x) = x * 2 ); Console.WriteLine({0} {1}, one(), doubleInt(1)); } } ``` The desugared (well, decompiled from IL - the arg_XXX_X variables are from the decompiler, not actually in the IL) C# looks like this: ``` public static void Main(string[] args) { object one = () = 1; object doubleInt = (int x) = x * 2; if (Program.Maino__SiteContainer0.p__Site1 == null) { Program.Maino__SiteContainer0.p__Site1 = CallSiteActionCallSite, Type, string, object, object.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, WriteLine, null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } ActionCallSite, Type, string, object, object arg_15C_0 = Program.Maino__SiteContainer0.p__Site1.Target; CallSite arg_15C_1 = Program.Maino__SiteContainer0.p__Site1; Type arg_15C_2 = typeof(Console); string arg_15C_3 = {0} {1}; if (Program.Maino__SiteContainer0.p__Site2 == null) { Program.Maino__SiteContainer0.p__Site2 = CallSiteFuncCallSite, object, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } object arg_15C_4 = Program.Maino__SiteContainer0.p__Site2.Target(Program.Maino__SiteContainer0.p__Site2, one); if (Program.Maino__SiteContainer0.p__Site3 == null) { Program.Maino__SiteContainer0.p__Site3 = CallSiteFuncCallSite, object, int, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) })); } arg_15C_0(arg_15C_1, arg_15C_2, arg_15C_3, arg_15C_4, Program.Maino__SiteContainer0.p__Site3.Target(Program.Maino__SiteContainer0.p__Site3, doubleInt, 1)); } ``` So you can see all the inline cache and binding machinery at work there. As far as I know there were 0 bytecode changes to introduce this feature; I certainly didn't have to implement any special bytecodes to support 'dynamic' in JSIL. There are certainly some aspects of the CLR bytecode that make dynamic languages easier/harder to build on top of it, though. I just don't know what they are. I know a lot of the pain was reduced with the addition of 'lightweight code generation' or LCG, which allows jitting a single method on the fly and attaching it to a given context (like a method) so that it can access private members. This is used heavily in dynamic languages on the CLR now. On Wed, May 14, 2014 at 10:54 PM, C. Scott Ananian ecmascr...@cscott.net wrote: On Wed, May 14, 2014 at 9:12 PM, Axel Rauschmayer a...@rauschma.de wrote: It'd be great if there was material on the limits of the JVM and the CLR. AFAICT these are the only virtual machines that are trying to be universal (run both static and dynamic languages well). Well, from experience, the JVM is/was handicapped by some incidental decisions in its original standard library[*] that have a large adverse impact on startup time. This has restricted the 'usefulness' of the JVM from its inception. There are projects to re-engineer the standard library around this, but they have been slow (and are not yet complete)[**]. Similarly, the support for dynamic languages is fairly recent (JDK 7, JavaScript implementation using these features in JDK 8), so it's a bit early to know
Re: Bytecode
On May 15, 2014, at 9:05 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: maybe relevant to this topic: https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/ WebKit chaps basically transform JS to LLVM compatible instructions Thanks for the shout-out! But I don't think it's quite relevant, since we transform to LLVM IR only after dynamic type inference has already happened - so the first N (for large N) executions of any code do not involve LLVM IR. Typical bytecode systems will use the bytecode as the basic underlying truth. Too bad they are testing from 2007 libraries such Prototype and inheritance.js :P We test many things. -Filip On Thu, May 15, 2014 at 8:14 PM, K. Gadd k...@luminance.org wrote: It's my understanding that the vast majority of the CLR's dynamic language support is at the runtime level, not the bytecode level. The bytecode is strongly typed (with lots of instructions/mechanisms for boxing, unboxing and type casts), and dynamic support is done through something called the 'DLR' that sits on top of the CLR. The DLR provides machinery for things like late binding and inline caches. For this C# snippet: ``` using System; public static class Program { public static void Main (string[] args) { dynamic one = (Funcint)( () = 1 ); dynamic doubleInt = (Funcint, int)( (int x) = x * 2 ); Console.WriteLine({0} {1}, one(), doubleInt(1)); } } ``` The desugared (well, decompiled from IL - the arg_XXX_X variables are from the decompiler, not actually in the IL) C# looks like this: ``` public static void Main(string[] args) { object one = () = 1; object doubleInt = (int x) = x * 2; if (Program.Maino__SiteContainer0.p__Site1 == null) { Program.Maino__SiteContainer0.p__Site1 = CallSiteActionCallSite, Type, string, object, object.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, WriteLine, null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } ActionCallSite, Type, string, object, object arg_15C_0 = Program.Maino__SiteContainer0.p__Site1.Target; CallSite arg_15C_1 = Program.Maino__SiteContainer0.p__Site1; Type arg_15C_2 = typeof(Console); string arg_15C_3 = {0} {1}; if (Program.Maino__SiteContainer0.p__Site2 == null) { Program.Maino__SiteContainer0.p__Site2 = CallSiteFuncCallSite, object, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } object arg_15C_4 = Program.Maino__SiteContainer0.p__Site2.Target(Program.Maino__SiteContainer0.p__Site2, one); if (Program.Maino__SiteContainer0.p__Site3 == null) { Program.Maino__SiteContainer0.p__Site3 = CallSiteFuncCallSite, object, int, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) })); } arg_15C_0(arg_15C_1, arg_15C_2, arg_15C_3, arg_15C_4, Program.Maino__SiteContainer0.p__Site3.Target(Program.Maino__SiteContainer0.p__Site3, doubleInt, 1)); } ``` So you can see all the inline cache and binding machinery at work there. As far as I know there were 0 bytecode changes to introduce this feature; I certainly didn't have to implement any special bytecodes to support 'dynamic' in JSIL. There are certainly some aspects of the CLR bytecode that make dynamic languages easier/harder to build on top of it, though. I just don't know what they are. I know a lot of the pain was reduced with the addition of 'lightweight code generation' or LCG, which allows jitting a single method on the fly and attaching it to a given context (like a method) so that it can access private members. This is used heavily in dynamic languages on the CLR now. On Wed, May 14, 2014 at 10:54 PM, C. Scott Ananian ecmascr...@cscott.net wrote: On Wed, May 14, 2014 at 9:12 PM, Axel Rauschmayer a...@rauschma.de wrote: It'd be great if there was material on the limits of the JVM and the CLR. AFAICT these are the only virtual machines that are trying to be universal (run both static and dynamic languages well). Well, from experience, the JVM is/was
Re: Bytecode
but you mentioned very old one I think nobody cares much anymore ;-) still very interesting how you reach that LLVM IR ! On Thu, May 15, 2014 at 9:27 PM, Filip Pizlo fpi...@apple.com wrote: On May 15, 2014, at 9:05 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: maybe relevant to this topic: https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/ WebKit chaps basically transform JS to LLVM compatible instructions Thanks for the shout-out! But I don't think it's quite relevant, since we transform to LLVM IR only after dynamic type inference has already happened - so the first N (for large N) executions of any code do not involve LLVM IR. Typical bytecode systems will use the bytecode as the basic underlying truth. Too bad they are testing from 2007 libraries such Prototype and inheritance.js :P We test many things. -Filip On Thu, May 15, 2014 at 8:14 PM, K. Gadd k...@luminance.org wrote: It's my understanding that the vast majority of the CLR's dynamic language support is at the runtime level, not the bytecode level. The bytecode is strongly typed (with lots of instructions/mechanisms for boxing, unboxing and type casts), and dynamic support is done through something called the 'DLR' that sits on top of the CLR. The DLR provides machinery for things like late binding and inline caches. For this C# snippet: ``` using System; public static class Program { public static void Main (string[] args) { dynamic one = (Funcint)( () = 1 ); dynamic doubleInt = (Funcint, int)( (int x) = x * 2 ); Console.WriteLine({0} {1}, one(), doubleInt(1)); } } ``` The desugared (well, decompiled from IL - the arg_XXX_X variables are from the decompiler, not actually in the IL) C# looks like this: ``` public static void Main(string[] args) { object one = () = 1; object doubleInt = (int x) = x * 2; if (Program.Maino__SiteContainer0.p__Site1 == null) { Program.Maino__SiteContainer0.p__Site1 = CallSiteActionCallSite, Type, string, object, object.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, WriteLine, null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } ActionCallSite, Type, string, object, object arg_15C_0 = Program.Maino__SiteContainer0.p__Site1.Target; CallSite arg_15C_1 = Program.Maino__SiteContainer0.p__Site1; Type arg_15C_2 = typeof(Console); string arg_15C_3 = {0} {1}; if (Program.Maino__SiteContainer0.p__Site2 == null) { Program.Maino__SiteContainer0.p__Site2 = CallSiteFuncCallSite, object, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } object arg_15C_4 = Program.Maino__SiteContainer0.p__Site2.Target(Program.Maino__SiteContainer0.p__Site2, one); if (Program.Maino__SiteContainer0.p__Site3 == null) { Program.Maino__SiteContainer0.p__Site3 = CallSiteFuncCallSite, object, int, object.Create(Binder.Invoke(CSharpBinderFlags.None, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) })); } arg_15C_0(arg_15C_1, arg_15C_2, arg_15C_3, arg_15C_4, Program.Maino__SiteContainer0.p__Site3.Target(Program.Maino__SiteContainer0.p__Site3, doubleInt, 1)); } ``` So you can see all the inline cache and binding machinery at work there. As far as I know there were 0 bytecode changes to introduce this feature; I certainly didn't have to implement any special bytecodes to support 'dynamic' in JSIL. There are certainly some aspects of the CLR bytecode that make dynamic languages easier/harder to build on top of it, though. I just don't know what they are. I know a lot of the pain was reduced with the addition of 'lightweight code generation' or LCG, which allows jitting a single method on the fly and attaching it to a given context (like a method) so that it can access private members. This is used heavily in dynamic languages on the CLR now. On Wed, May 14, 2014 at 10:54 PM, C. Scott Ananian ecmascr...@cscott.net wrote: On Wed, May 14, 2014 at 9:12 PM, Axel Rauschmayer a...@rauschma.de wrote: It'd be great if there was material on the limits of the JVM and the CLR. AFAICT these are the only
Re: Assignment to method invocation result
On Thu, May 15, 2014 at 8:47 PM, Rick Waldron waldron.r...@gmail.com wrote: I imagined .= would do both, but I don't think my suggestion should be taken seriously. In fact, your example illustrates a major flaw (that exists in either proposal/suggestion), that I don't immediately know how I would answer: var o = { foo: bar }; o .= foo; Is `o` now a string with the value bar?? I think that would cause more problems than its worth. Yes, that's exactly what it would do. This sort of pattern is even reasonably common when doing tree-walking, for example: you see a lot of node = node.left; or whatnot. ~TJ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss