Download

Go here to download ready-to-run and source distributions of Jangaroo. more...

Showing posts with label jooc. Show all posts
Showing posts with label jooc. Show all posts

Monday, January 30, 2012

Simulating ActionScript Rest Parameter in JavaScript

Let's continue the series on simulating ActionScript language features in JavaScript with something similar to optional parameters, namely the ... (rest) parameter.
ActionScript allows you to specify that an arbitrary number of parameters follow the usual named and optional parameters by prefixing the last parameter with three dots (see "The ... (rest) parameter"):

 1 public function join(separator:String, first:String,
                        ...strings:Array):String {
 2   strings.splice(0, 0, first);
 3   return strings.join(separator);
 4 }

As you can see, all formal parameters following the named parameters are combined into an array. Since the ... (rest) parameter is always of type Array, you can safely skip the type annotation.

The arguments variable in JavaScript
Fortunately, JavaScript offers access to all formal parameters of a function call, even if they are not declared as named parameters of the function, through the arguments variable. For some reason, this variable does not actually hold an Array. Instead, it is an array-like Object with indexed properties and a length property. This means that we cannot invoke Array methods directly on arguments, but there is a trick: Call the slice function retrieved from the Array prototype, as described e.g. here, and the result is a "real" Array:

Array.prototype.slice.call(arguments)

At the same time, we can cut off the named parameters, since the first parameter to slice is the index where to start slicing from the source array. Thus, the resulting JavaScript code generated by the Jangaroo compiler jooc is the following:

 1 function join(separator, first) {
     var strings = Array.prototype.slice.call(arguments,2);
 2   strings.splice(0, 0, first);
 3   return strings.join(separator);
 4 }

Note the slice parameter value 2, which takes care of cutting off the two named parameters. Also note how Jangaroo only adds an auxiliary statement, but keeps all other statements exactly the same, which makes debugging a lot easier.

Side note: arguments is an array is AS3
The only thing Jangaroo currently does not yet implement correctly is that in ActionScript, the arguments variable is actually always an array! Thus, instead of writing

 1 public function joinComma() {
 2   return arguments.join(",");
 3 }

which would be fine in ActionScript, in Jangaroo you currently have to use

 1 public function joinComma(...args) {
 2   return args.join(",");
 3 }

This is to save the overhead of always converting arguments into an array. Of course, the compiler could analyze whether arguments is used as an Array at all and only add the conversion code then. I just filed the bug as issue JOO-12.

Saturday, January 28, 2012

Simulating ActionScript Parameter Default Values in JavaScript

To continue our series on simulating ActionScript language features in JavaScript, this episode is about parameter default values.
In contrast to JavaScript, ActionScript allows to specify a default value for a function (or method) parameter, like so:

 1 public function insult(s = "fool") {
 2   return "you " + s;
 3 }

The idea is that when the method is called without providing a value for parameter s, the default value "fool" will be used. Details on what additional rules hold for declaring parameter default values are given in the Adobe documentation on function parameters and a bit less reference-like e.g. in a tutorial on Ntt.CC.

Why, it's easy, isn't it?
A straight-forward implementation in JavaScript (similar to the solution suggested by Bernd Paradies for FalconJS) would be to replace undefined paramter values by their default value:

 1 function insult(s) {
     if (s === undefined) {
       s = "fool";
     }
 2   return "you " + s;
 3 }

(We could now start a discussion on whether it shouldn't be
     if (typeof s === "undefined") {
because in JavaScript, undefined may be redefined, but anybody who does so is, excuse me, a fool.)
In JavaScript, when you omit a parameter when calling a function, the parameter value indeed is undefined. But it is a fallacy to assume that every undefined parameter must be replaced by its default value! Consider the following ActionScript class:

 1 public class DefaultParameterTest {
 2
 3   public function DefaultParameterTest() {
 4     trace("1. " +  insult ("nerd"));
 5     trace("2. " +  insult ());
 6     trace("3. " +  insult (undefined));
 7   }
 8
 9   public function insult(s = "fool") {
10     return "you " + s;
11   }
12 }

What do you think will be traced? Try it out, and you'll see that explicitly handing in undefined does not trigger the default value! Thus, the result is
1. you nerd
2. you fool
3. you undefined

(Careful, never call a JavaScript programmer "you undefined"!)
Using the straight-forward JavaScript implementation, the result would be
1. you nerd
2. you fool
3. you fool

As you can see, using parameter default values depends on the number of formal arguments, not on their value. This is the reason why they are also called optional parameters, and why after a parameter with a default value, all following parameters must also specify a default value.

Getting it right
Thus, the correct JavaScript equivalent (as generated by the Jangaroo compiler jooc) is to check the number of formal parameters. Fortunately, this can be realized by checking arguments.length:

 1 function insult(s) {
     if (arguments.length < 1) {
       s = "fool";
     }
 2   return "you " + s;
 3 }

In fact, this solution even provides better runtime performance when using multiple optional parameters, since multiple arguments.length checks can be nested, while the undefined checks in the straight-forward solution would be sequential. Consider the following example:

 1 public function foo(p1, p2, p3 = 3, p4 = 4) {
 2   return p1 + p2 + p3 + p4;
 3 }

The JavaScript fragment generated by Jangaroo looks like so:

 1 function foo(p1, p2, p3, p4) {
     if (arguments.length < 4) {
       if (arguments.length < 3) {
         p3 = 3;
       }
       p4 = 4;
     }
 2   return p1 + p2 + p3 + p4;
 3 }

Jangaroo even optimizes undefined default values, since left out actual parameters are undefined in JavaScript, anyway.

Alternative Solutions
We also thought of using a switch statement, generating code like the following:

 1 function foo(p1, p2, p3, p4) {
     switch (arguments.length) {
       case 0:
       case 1:
       case 2:
         p3 = 3;
         // fall through
       case 3:
         p4 = 4;
     }
 2   return p1 + p2 + p3 + p4;
 3 }

At first sight, this solution seems more efficient, because arguments.length is only evaluated once. The reason why we still chose the nested if code layout is that the switch solution becomes either long or non-robust when using many non-optional parameters. Note the lines case 0: and case 1: in the example above: although the method should never be called with less than two parameters (since the first two are not optional), we want to handle that case, too, since Jangaroo code may be called from JavaScript, where no function signature check is performed. When the function is called with fewer parameters than required, you would still expect the default values to pop in. So the case statements would pile up when there are many non-optional parameters. However, I could imagine a mixed solution like the following:

 1 function foo(p1, p2, p3, p4) {
     switch (Math.max(arguments.length, 2)) {
       case 2:
         p3 = 3;
         // fall through
       case 3:
         p4 = 4;
     }
 2   return p1 + p2 + p3 + p4;
 3 }

The most intelligent solution would be to dynamically decide whether the prior length check pays off against adding several case statements. I guess I'll add that to the Jangaroo backlog!

Tuesday, December 6, 2011

Simulating ActionScript in JavaScript: Private Members Cont'd

In the first blog post about simulating private members in ActionScript, I compared different solutions to represent private members in JavaScript. The solution implemented by Jangaroo is to rename private members, so that they do not name-clash with private members of the same class, defined on a different inheritance level.
Bernd Paradies asked how Jangaroo solves untyped access to private members. Since the answer is rather extensive, I'll dedicate this follow-up post to the topic.

The short answer is: it's the nature of the beast. Untyped access to private members cannot be detected at compile time. However, potential access to private members can be detected at compile time and generate code that repeats the check at runtime, although Jangaroo does not implement this at the moment.

Typed Private Member Access
Let's recall the typical way to access private members, which can easily be detected by the Jangaroo compiler:

 1 public class Foo {
 2   private var foo:String = "bar";
 3   public function getFoo():String {
 4     return foo;
 5   }
 6 }

As foo in line 4 is resolved to a field of the class, and there is no implicit this access in JavaScript, the Jangaroo compiler adds this. before foo. Also, as field foo is declared private, the compiler renames it to foo$1 (see previous blog post) and thus generates the following JavaScript code for the body of method getFoo():

 4     return this.foo$1;

Where is My Type?
Now consider the following code (which does not really make sense, but illustrates the point):

 1 public class Foo {
 2   private var foo:String = "bar";
 3   public function getFoo():String {
 4     var untypedThis:Object = this;
 5     return untypedThis.foo;
 6   }
 7 }

Of course, in this simple example it would still be possible to determine the runtime type of untypedThis statically, but it is easy to imagine a situation where this is not possible. In the current Jangaroo implementation, the following JavaScript code would be generated for the body of method getFoo():

 4     var untypedThis = this;
 5     return untypedThis.foo;

As you can see, the compiler fails to detect that foo actually refers to the private member, does not rename the access to foo$1, and thus the undefined value of untypedThis.foo would be returned.

A (partial) solution is to let the compiler detect any expression of the form untyped.private-member and generate code that takes into account the runtime type of untyped, like so:

 5     return untyped[untyped instanceof Foo ? 'foo$1' : 'foo'];

Trusting today's JavaScript JIT compilers' optimizations, this code should be moved to a utility function to avoid double evaluation of the untyped expression (which could have side effects):

 5     return Foo.$class.get(untyped, 'foo');
 
where Foo.$class provides access to Jangaroo's "meta class" of Foo, and get() would be implemented there like this:

  public function get(object:Object, property:String):* {
    return object[object instanceof this.publicConstructor ?
      property + this.inheritanceLevel : property];
  }

The Weak and the Wicked
Looking at ActionScript carefully, you'll notice that the identifier or expression left of the dot does not even have to be untyped, but may just be typed with a more general type, and the same scenario may apply. For example, assume our class Foo is a subclass of dynamic class Bar, we could replace Object by Bar, and the example would still work! Even if Bar is not dynamic, we could access the private member foo through a local variable of type Bar using square brackets, like so:

public class Foo extends Bar {
  private var foo:String = "bar";
  public function getFoo():String {
    var weaklyTypedThis:Bar = this;
    return weaklyTypedThis['foo'];
  }
}

The Flex compiler does not complain, and at runtime, in Flash, indeed the private member is accessed. Compare this to the following example, where we try to access the private member of a superclass:

public class Baz extends Foo {
  public function Baz() {
    super();
    var superThis:Foo = this;
    trace(superThis['foo']); // is undefined, not "bar"!
  }
}

Maybe you'll be surprised that the result is not any kind of access violation, but simply undefined—the private member of the superclass is simply not visible for the subclass! This is well emulated by Jangaroo through renaming private members. The Jangaroo compiler just has to take care to detect every correct access of a private member and rename the property upon access.

Turing Strikes Again
Things get even nastier when the property is a dynamic expression. Consider

  return this[veryComplicatedComputation()];

Here, too, we'd have to generate

  return Foo.$class.get(this, veryComplicatedComputation());

and extend the utility function by a runtime check whether the property is actually a private member name:

  public function get(object:Object, property:String):* {
    return object[object instanceof this.publicConstructor &&
      this.getMemberDeclaration("private", property) ?
        property + this.inheritanceLevel : property];
  }

Summary
Taken together, the important criterion when to generate code for possible private member access is not whether the left-hand expression of the dot is untyped, but the compiler has to check whether the complete property access is not typed. This is the case exactly when the property is not a compile-time constant or when the property cannot be resolved statically within the type of the expression, and in any case, the type of the expression must be a supertype of the current class or the current class itself.

To wrap up, the compiler would have to generate a call to the dynamic access function if and only if
  1. the left-hand expression could have a runtime type compatible to the current class and 
  2. the property expression could be one of the current class's private members.
Here, could means that it may be, but is not certain at compile time. If both conditions are certain at compile time, the compiler knows for sure that the code represents access to a private member, and can simply use the renamed property.

One more thing: I have been talking about read access of private members. The same strategy would have to be applied when writing members, resulting in another utility function set(object, property, value).

Optimize?
Of course, we could optimize runtime performance by using specific utility functions for the following three different cases:
  1. The property is definitely a private member, but the left-hand expression may or may not be of the current class: check instanceof only.
  2. The left-hand expression is definitely of the current class, but the property may or may not be a private member: check the property only.
  3. Both the left-hand expression may or may not be of the current class, and the property may or may not be a private member: check instanceof and the property.
However, my guess is that this optimization is not necessary. Firstly, checking instanceof and whether some string is contained in a fixed and not very large set are cheap operations. Secondly, when using ActionScript (and not untyped JavaScript), you should avoid untyped access of properties whenever possible. Thus, the situation is a rare case, and would only be implemented for full ActionScript semantic compatibility. If the developer wants better performance, she can either insert a type cast to convert the property access to a typed one, or move dynamic properties to a dedicated object whose type is statically incompatible with the current class (e.g. use Dictionary), and thus no runtime check would be generated.
If this solution proves to inflict significant runtime overhead, the compiler should issue a warning when it has to generate runtime checks.

Friday, July 18, 2008

Former Life and Birth of Jangaroo

Today, CoreMedia released a first version of the Jangaroo language and tools as Open Source. This was a wonderful moment for me, because this little project has a long history and played an important underpart in my professional life at CoreMedia over the last years. Please read about it, download, apply, spread the word! Be prepared to develop JavaScript like you never did before! The new Web site should offer you everything for a quick start. If not, feel free to ask! In this first blog post, however, you are going to hear Jangaroo's story, which covers its birth, coming of age, and reincarnation, if you want.
Trying Not to Be Eclectic
When in 2003, I had my first deeper dive into JavaScript, I never had thought it would become a passion. As most Java developers, I despised the style of eclectic programming that was then common among JavaScript hackers: To implement some requirement, they didn't use frameworks or libraries, but grabbed code snippets from other Web pages or forums and somehow assembled them to make them work on their Web pages. My impression was that it is hardly possible to implement serious business in such a patchwork language. But I had to, since a new Web application for CMS content entry waited to be designed and implemented.
Patching a Patchwork Language
My colleague Andreas Gawecki surely agreed on that and decided that, before even starting to dirty our hands on pure JavaScript, we needed a tool to transfer at least some of the amenities of Java to the JavaScript world. But because that was in the days before the Web 2.0 hype and the JavaScript Renaissance, there was no such tool. If you know Andreas, you may be able to imagine what happened: Within a week or so, he had gone through the JavaScript 2 / ECMAScript 4 standard proposals and came up with a compiler that could translate a subset of JavaScript 2 language features to JavaScript 1.x! Of course, Andreas had done research on how classes are usually simulated in JavaScript, and of course he had implemented those JS2-features a Java developer would need most desperately when having to program in JavaScript. I was one of his first Guinea Pigs, and also his primary sparring partner for the language. We started developing tons of JavaScript 2 code, because there were not even JavaScript 1 frameworks available, and we had to do all the cross-browser compatibility code ourselves. Andreas even implemented a Rich Text Editor that had features like table editing that were rare in 2003 - and all that using the JavaScript 2 subset and his compiler.
One Thing Leads to Another
This first shot of the compiler was simply named jscc (JavaScript Class Compiler), and the source file extension was .jsc, so the language was also called JSC. Soon, more tools and libraries followed: Holger Tewis implemented a javadoc-counterpart, naturally called jscdoc, that tricked Java doclets into generating HTML API documentation for JSC programs. I did a port of JsUnit to JSC, needless to say called JscUnit, in about two days (and of course its self-tests were green then). We experimented with writing IDE plug-ins for the unfinished language. Having learned from the WebEditor, we implemented another UI framework, which we so far only used for popping up a context menu on preview Web pages to let the user invoke content-related actions (sounds a bit like breaking a fly on the wheel, doesn't it?).
I loved working with JSC, but to be honest it had some serious drawbacks:
  • There was no real IDE support.
  • No type checker, types are just remarks used for API documentation.
  • Bugs and request were not fairly tracked and never really tackled.
  • No class dependencies or automatic class loading: each class file had to be listed, and even in the right sequence before all its depending classes.
Worst, there was almost no documentation and the build process was tied to our primary product. JSC was suffering the typical fate of an internal development tool that had no (paying) customer, although a lot of value or at least potential. At that time, our company grew, and even other projects in the very same company did not use JSC for their JavaScript development. I felt there was something going wrong.
Time for a Change
CoreMedia went through some changes, which opened up new possiblities. We evolved to a learning company, where all members are given time for "peer group" work, i.e. work in small groups of people who pursue a common goal and handle a topic of individual choice. Luckily, I found fellows who were, like me, interested in reanimating JSC. The new spirit and transparency of our company was the perfect breeding ground for the idea to release JSC to the public, as Open Source. It was the perfect candidate:
  • En vogue topic.
  • Focussed, general purpose tool.
  • Not too big to handle.
  • Nothing anyone would want to sell: development tools are hard to sell, anyway, and these are not our company's focus.
  • We had to document and clean up, anyway, so hardly any additional cost.
The main goal of the peer group, consisting of Andreas Gawecki, Olaf Kummer, Matthias Buse, Mark Michaelis, and myself, was to prepare a decision memo convincing CoreMedia to spend resources on our first real Open Source project.
At that time, JavaScript really enjoyed a renaissance and AJAX was a hype. Interesting new articles about JavaScript mushroomed and inspired me to create a new JSC runtime supporting features like private and protected members, lazy class initializing, and even better readable compiled code. After several iterations, we decided to skip "really private" and protected members for performance reasons, but nevertheless found a solution that does the job to avoid unexpected name clashes. We also updated the language syntax to the latest standard proposals. Suddenly, IDEs started to support ActionScript 3, which is also an ECMAScript 4 language, so we could benefit from that, too.
We were overcoming most disadvantages of JSC. In other words, we had even more to offer than what we had used successfully as an internal tool for years.
The peer-group found that JSC needed a proper name: it should be Web-2.0-ish, cool, foolish, looney (add your favorite adjectives containing oo-s), and artificial, so that we could still grab the domain, the blogger subdomain (sic!), the user ID for community xyz, and so on. All our peer groups have rather silly animal names, and we were True Kangaroo. Replacing the first letter by a JavaScript J and keeping the popular oo-s finally led to Jangaroo. I guess the cool name must have been the critical factor when CoreMedia decided to give us a go.
Walking the Talk
In the execution phase, Masiar Bostanipoor (Web site) and Dennis Homann (build infrastructure, tutorial) joined the team. Andreas and Olaf rounded off compiler (now coherently called jooc) and runtime (where I helped a bit). Olaf wrote most of the language and compiler documentation. Kudos to numerous CoreMedians who helped us with the project, in no particular order and surely not complete: Thomas Stegmann, Gunnar Klauberg, Uli Henningsen, Tobias Baier, Jan Brauer, Carsten Böttcher, Stefanie Wegener, and Christian Pesch.
We used the project time CoreMedia granted us mainly to come up with a stable infrastructure and an appealing presentation (at least we hope so), not to create more tools. We got the domain jangaroo.net, created a Web home for Jangaroo, started this blog, wrote documentation, set up a proper build process involving a Maven repository, cared about license issues (German license jurisdiction is a nightmare!), and so on. Of course, some infrastructure is still missing, most importantly a forum and a bug tracker -- we are working on that, please bear with us! Until then, please comment in this blog for public discussions, and e-mail for direct communication. We also have a twitter user Jangaroo, feel free to follow if you like! Many of the tools and libraries mentioned here may follow jooc, so stay tuned!
I hope you have enjoyed hearing about Jangaroo's first life as JSC and its rebirth as an Open Source project. What I described is just the way I personally remember and feel about things. In the future, be prepared to find a bit more technological facts in my postings...