- Scheme: this would have been a much better choice, because it supports integers and has a compact object representation instead of representing everything with hash tables. Bad point: all objects are boxed (like in JS). Good point: tail calls are handy when compiling all kinds of control structures.
- Java: As an IL to compile down to this would have been better than Javascript. Good points on top of Scheme: unboxed primitive types, static typing means fewer runtime checks. Bad point: lack of tail calls.
- ML: excellent choice: has both unboxed primitives and tail calls.
I challenge you to find a language that would have been a worse choice than Javascript. It may turn out that by working really hard on smart runtimes and compilers you can get OKish performance out of Javascript in some cases, but that doesn't mean that it's a good choice for an intermediate language. A ML compiler that just translates to LLVM IL as simply as possible without doing any optimizations itself will easily beat the highly optimized Javascript engines we have today.
You are right on integers though, and other types of memory block in general, they are trickier to fix in a javascript engine. Surely the best IL is LLVM IL though, since it was designed so everything can compile down to it.
That sounds like what Self does, too. See the excellent paper, "An Efficient Implementation of SELF" (http://selflanguage.org/documentation/published/implementati...).
The Self bibliography page (http://selflanguage.org/documentation/published/index.html) has a lot of other content applicable to dynamic languages in general, too.
LLVM IL would be excellent for speed. The problem is that it's not memory safe (i.e. it allows reading and writing to arbitrary memory locations). NativeClient at Google is trying to solve that. http://code.google.com/p/nativeclient/
I've had several mid-end managed switches where the web configuration UI used it and was unusable outside of IE with no sign as to why unless you read the source.
Javascript is a good enough (New Jersey-style) solution.
Why "fix" it?
With Javascript, unfortunately, it didn't work out so well - a bunch of early bugs (which could have been quickly fixed) were preserved when Microsoft made a bug-compatible clone for IE, and then became part of the ECMAScript standard in 1996. This derailed efforts to improve the language - there is a lot of work on sophisticated implementations now, but the spec itself is buggy.
People invoke "Worse is Better" as retroactive justification for all kinds of engineering blunders, but it's a bit more limited in scope. Here you go: http://www.jwz.org/doc/worse-is-better.html
Unix didn't get "fixed" later.
I'd say Unix got more of its warts fixed than JS did, but that's only a difference of degree.
Mainly: The whole "Worse is Better" thing works better when you don't get stuck maintaining reverse compatibility with your early releases.
When did Unix get fixed?
There are plenty of examples of languages that are worse than Javascript for the web. Java being a perfect example. Java and Javascript co-existed on the web for quite some time (in theory they still do). Java is based on a "proper" IL. And yet here we are, talking about some hypothetical new IL to replace Javascript, despite the fact that there is no guarantee it would actually be better, as the historical example of Java has shown us.
You need to get more than just the VM "right", there's a billion other factors, Java screwed up, Javascript hit the mark (despite its many other flaws). Perhaps LLVM is the future of web applications, it's too soon to tell. What I do know is that Javascript may not be perfect but it's still fundamentally good, and powerful enough (largely through closures and prototypes) to allow for robust workarounds to its flaws (jQuery, coffeescript, etc.)
Yup, JS arrays look crazy when you are used to C and pointers (I was shocked when I first found out).
That's why WebGL folks had to come up with typed arrays:
https://cvs.khronos.org/svn/repos/registry/trunk/public/webg...
The boxing part is untrue. Even on 32-bit systems (that have word-aligned addressing, which all current 32-bit systems do), you can get 6 arbitrary type tags by using up the three least significant bits of a pointer (6 and not 8 because you use up two of the possible tag values for even/odd immediate integers (fixnums)).
Tail calls are overrated, maybe you're thinking about continuations? Those would have been truly terrible - you get all the downsides of concurrency with no benefits. One of the reasons arbitrary crap JS code runs as well as it does is because there's no possibility of concurrency. The browser event-loop model is a good one.
"- Java: As an IL to compile down to this would have been better than Javascript. Good points on top of Scheme: unboxed primitive types, static typing means fewer runtime checks."
Don't forget: getting sued by Oracle.
Java blows in every way compared to JavaScript. If Netscape had put Java instead of JS into Navigator the web would be a very different place today, because no one would have used it [Java].
"ML: excellent choice: has both unboxed primitives and tail calls."
In 1995? Give me a break, or a time machine.
You're right. Scheme implementations usually have unboxed fixnums and other types. However Scheme systems do not usually support user defined unboxed objects, like C#, C and ML do.
> Tail calls are overrated, maybe you're thinking about continuations? Those would have been truly terrible
I agree, I did mean tail calls. Tail calls may not be so good for programming with, but they are good for compiling to, because you can easily encode your control structures like while, for, until, state machines and more exotic forms of looping to them. You can also compile (parts of) code in continuation passing style without blowing the stack, which is hard to do efficiently if you don't have tail calls.
The reverse is not true, you cannot easily express tail calls on top of the usual control structures like while. This is why Scala and Clojure still don't have support for tail calls.
> Java blows in every way compared to JavaScript. If Netscape had put Java instead of JS into Navigator the web would be a very different place today, because no one would have used it [Java].
I'm not arguing that Java is better than Javascript for programming in. It's just a better target for compilers.
> In 1995? Give me a break, or a time machine.
Do you have any arguments to back up why ML would not be a better IL than JS?
It seems to me that you are arguing that these languages are not better than JS for programming in, but that is not what I claimed.
That's because Scheme has to support type safety for arbitrary code loaded at run-time. Exactly like JavaScript has to do when the web browser GETs a script. Exactly what any of the other proposed ILs would have to do as well.
"I agree, I did mean tail calls. Tail calls may not be so good for programming with, but they are good for compiling to, because you can easily encode your control structures like while, for, until, state machines and more exotic forms of looping to them. You can also compile (parts of) code in continuation passing style without blowing the stack, which is hard to do efficiently if you don't have tail calls.
The reverse is not true, you cannot easily express tail calls on top of the usual control structures like while. This is why Scala and Clojure still don't have support for tail calls."
A better argument can be made for gotos than tail calls in this case. JavaScript already has gotos in the form of labels and break.
Tail call faking doesn't always have to have a trampoline overhead cost. Take a look at Scheme2JS for how they do it (http://www-sop.inria.fr/indes/scheme2js/)
"I'm not arguing that Java is better than Javascript for programming in. It's just a better target for compilers."
JavaScript provides run-time types and extensive reflection and introspection facilities. This makes it relatively straightforward to write something like Parenscript. OTOH trying to compile even a static subset of Common Lisp to C or Java is pretty complicated.
"Do you have any arguments to back up why ML would not be a better IL than JS?"
Your original statement was: "I challenge you to find a language that would have been a worse choice than Javascript." Given the state of ML implementations in 1995, I think it would have been a worse choice.
"It seems to me that you are arguing that these languages are not better than JS for programming in, but that is not what I claimed."
And you seriously think people would have first run out and built compilers from other languages to the "hypothetical better than JavaScript" language rather than use the latter directly? Because that's not what actually happened.
Actually, no, it doesn't. I don't know anything about JavaScript.