Category Archives: Uncategorized - Page 2

Attributes with haXe (AKA Metadata or Annotations)

Many languages support metadata in the form of additional information attached to classes, methods or variables. In this post I provide a sample implementation to produce such a thing in haXe.
I created a class Attributes (source code attached to this post) with the following signature:

class Attributes {
public static function of(cls : Class, ?field : String) : Attributes;
public var parent(default, null) : Attributes;
public function exists(key : String) : Bool;
public function get(key : String, ?alternative : String) : String;
public function set(key : String, value : String) : Void;
public function isInherited(key : String) : Bool;
public function keys() : Iterator;
public function iterator() : Iterator;
public function toString() : String;
}

Instances of the class cannot be created directly but they must be obtained using the static method Attributes.of(). The first parameter is the type of the class we want to retrieve attributes, the second optional parameter is a field of that class (it works with either static or instance members). The class is very similar to Hash with the exception that attributes are inherited; so class B that extends class A can inherit or redefine the attributes of B.

Let’s see how we can use the class.

import attributes.Attributes;
import haxe.rtti.Infos;

/**
* @author Franco Ponticelli
* @year   2009
*/
class Main implements Infos {
/**
* @role entry point
*/
static function main() {
trace("attributes of Main: " + Attributes.of(Main));
trace("attributes of Main.main: " + Attributes.of(Main, "main"));
}
}

The output is:

Main.hx:15: attributes of Main: { author : Franco Ponticelli, year : 2009 }
Main.hx:16: attributes of Main.main: { role : entry point }

In the first case we have retrieved the attributes of the class Main while in the second the attributes of its method main().

If you want to try you can’t forget about two things: classes that provide attributes must implement haxe.rtti.Infos and you must add the directive -D use_rtti_doc when you compile your project. The latter informs the compiler that nodes must be included in the generated code.

One nice thing about attributes is that they are both “code” and documentation. Attributes can have a lot of applications, in ORM they can be used to wire a class name to a SQL table name or to map fields and relations to columns; in controllers they can be used to bind a method to certain credentials or templates; in a unit testing system they could be used to mark the functions that are test methods.

There is one thing are a couple of things to consider before embracing this technique, rtti info are stored as XML in the code and the parsing can be slow (the provided implementation caches the results to speed things up) and there is currently a bug in the -D use_rtti_doc: overrode methods do not bring their documentation so attributes attached to them are simply discarded. Hopefully the latter problem will be addressed soon. (bug fixed in CVS, version 2.05 will be bug free)

download here: Attributes.v.1.0

Friendly types with haXe

If you are experienced with haXe you’ll know that its type system permits to catch a lot of errors at compile time simply veryfing that parameter/member types are correctly used in your application. Members can only have two access modifiers: public or private. But what if you want to emulate something like the “friend” modifier that exists in other languages?

Let’s see a practical example.

class Test {
  static function main() {
    var c = new Container();
    var n1 = c.add(new Item("John"));
    var n2 = c.add(new Item("Jane"));

    trace(c);
    trace(n1);
    trace(n2);
  }
}

class Container {
  public function new() {
    children = new List();
  }
  public function add(n : Item) {
    children.add(n);
    return n;
  }

  public inline function iterator() { return children.iterator(); }
  public inline function count() { return children.length; }

  public function toString() {
    return "[Container] has " + children.length + " children";
  }

  var children : List;
}

class Item {
  public var parent(default, null) : Container;
  public var name(default, null) : String;
  public function new(name : String) {
    this.name = name;
  }
  public function toString() {
    if(parent != null)
      return "[Item] " + name + " has " + (parent.count() - 1) + " sibblings";
    else
      return "[Item] " + name + " has no parent";
  }
}

This flat hierarchy proves my point because something is missing, the Item instances never receive a reference to their container and the field parent is always null. The output trace is:

Test.hx:8: [Container] has 2 children
Test.hx:9: [Item] John has no parent
Test.hx:10: [Item] Jane has no parent

I don’t want to expose parent as public or pass it in the Item constructor because I want my hierarchy to be composed just using the method add (in real life a lot of things can lead to that decision).
With a friend I could just add this to Item:

// friend method
private function setParent(p) {
  parent = p;
}

But how do you call that safely from outside the Item class? It is private so it cannot be invoked directly … you can use untypedto make the compiler skip the types check on that call; but what happens if you want to change the name of setParent toset_parent at a later point and forget to change the untyped call too? The compiler will not spot the error and you’ll only catch it at runtime when some strange behavior will pop.

Here it comes the solution, change the Container.add function this way:

public function add(n : Item) {
  children.add(n);
  var p : { private function setParent(p : Container) : Void } = n;
  p.setParent(this);
  return n;
}

I have created a temporary var p whose type is exactly and only what we need to access the “friend” method. It works without any casting or untyped access because the type of “p” is structurally a sub-type of Item making it implicitly compatible. We can callsetParent from p because typedefs define a structure but do not impose any access limit.

Now the output is what expected at first:

Test.hx:7: [Container] has 2 children
Test.hx:8: [Item] John has 1 sibblings
Test.hx:9: [Item] Jane has 1 sibblings

If and when you will change the name of Item.setParent the compiler will throw an error notifying that Item is no more compatible with the type of p.
Many thanks to Nicolas Cannasse that suggested this unusual way of using typedefs on the haXe mailing list.

 

Optimize cache for autoloading classes in haXe/PHP

The code generated using haXe/PHP uses the PHP autoloading feature to dynamically load classes definitions when they are required. This method has many advantages but a drawback too; the thing is that the autoloading function (hidden in php.Boot) needs to scan the lib folder to look for type definitions. It is not really a big work since only the file names are read without the need to immediately open the files, nevertheless this work is made each time the page is accessed. To reduce the impact of this operation you can simply create a cachefolder at the same level of lib and give it the proper attributes for PHP being able to write files in there. On the next use of your script, a new file haxe_autload.php will be automatically generated and will contain all the info required by the autoloading function.

As you can guess, the impact of this feature is proportional to the number of classes included in your project.

Be warned that it is better to use the cache only on production sites because during development it is quite normal adding new classes and the cache will not include them unless thehaxe_autload.php file is manually deleted. If you need to upgrade your production code, remember to delete that file first!

edit: I’ve made a few informal tests compiling a project that generates 76 files but uses only a few of them to maximize the impact of the cache trick. The results are the following but remember that your mileage may vary greatly and you can also find out that you will not have any benefit from abilitating the cache feature.

Execution time:
198ms no cache
151ms cache activated (31% speed gain)

 

haxe.Stack for PHP

Starting from haXe 2.04 the PHP generator supports the -debug switch. The implementation is almost identical to the haXe/JS one where the function calls are stored in a stack. You can see it working when you have an uncaught exception or using the haxe.Stack methods as in the following example:

import haxe.Stack;
class Test {
  static function main() {
    var f = function() { ref(); };
    f();
  }

  static function ref() {
    throw "error";
  }
}

The output will be:

uncaught exception: error

Called from Test::ref
Called from Test::main@4
Called from Test::main

Note that @4 means that a local function is involved.
You can obtain the same output without generating an exception replacing throw "error" with:

trace(Stack.toString(Stack.callStack()));

Is it appropriate to remove the -debug switch when compiling for deployment since it adds extra code to your output.

 

Closr.it

Closr.it is now open to the public by a few weeks. This open initiative enables users to freely store and share high-resolution images. Images are processed on the server and partitioned into tiles as much as Google Maps does for its aerial pictures.
Visup is the smart company behind Closr.it and they have chosen haXe to develop the Flash viewer.

Here comes an example that I have uplodaded, be sure to try the fullscreen mode:

haXe/PHP in version 2.01, what’s next?

If you are a haXe user you already know that PHP is already an official target of the haXe platform. The second version that includes PHP is 2.01 and it has reached a nice level of stability mainly thank to Nicolas who has adopted it for his personal website. He pointed out some annoying bugs that have been promptly fixed by me :) . But unfortunately for my personal life I realized that I still have a lot to work on to make haXe/PHP still better.

In CVS I have already made a radical change of direction to favor wrapping arrays into objects instead of using them directly. This has several implications; the main reason behind that is that in this way the compiler does not have to worry about passing by reference instead of by value. Other very important steps I will have to make in the future are optimizing as much as possible the generated code for performances, adding a debug version and creating as much tutorials as possible ;)

 

Strands™ Summer 2008 haXe Project Announcement

Thanks to Justin Donaldson the Strands™ Summer 2008 haXe Project is a reality now. You can find the full announcement here. It is very nice to know that the industry is interested in haXe and ready to invest on it. If you are a student, don’t loose the opportunity to earn $4.500 developing something that can be really useful to you and to the community.

haXe/PHP Alpha 2 Status

The second release of haXe/PHP is available.

I would like to discuss here the development status of the project and maybe receive some feedback.

First of all, my todo list is almost empty and this is a good thing. The generator and the class libraries have made a big step forward from the first alpha. I consider the generator usable and I am actually using it for two small projects I am developing.

The last step I have to accomplish before passing to the beta status is to workaround some edge cases on strings and arrays. In the current implementation, strings (and arrays) are not encapsulated in objects and the compiler tries to resolve any occurrences in the following way:


"mystring".substr(0, 2);

is generated as:


php_Boot::substr("mystring", 0, 2);

The big advantage of this is that the code is fast but it leaves quite a big problem behind:


var d : Dynamic = "mystring";
d.substr(0, 2);

generates:


$d = "mystring";
$d->substr(0, 2);

In this case the compiler cannot correctly interpret the code and generates an invalid field access on a string value. The most obvious solution is to drop the native implementation and wrap strings (and arrays) into objects as Neko does … I’ve tried it and it has been painful … not the implementation of course but the performances have dropped to unusable. My full test suite that usually took a few milliseconds to be executed, passed to take a few (too much) seconds. The other solution, the one I am trying to figure out how to implement, is to wrap into objects only those occurrences that are not known for sure. So the above example would be transformed into:


$d = php_Boot::__box("mystring"); // now $d is an instance of php_HString
$d->substr(0, 2);

where __box is a function that makes a runtime typecheck on its argument and wraps it in a proper object if required. This function comes with the complementary __unbox that makes the reverse. This seems a good solution to me but I know it will not be easy to implement because the compiler will have to make a lot of look-ups to match the expected types with the passed types …. maybe Nicolas has some good advices on this ;-)

The other issue is the standard library. Many of the classes in the neko package have been implemented in php (Lib, Sys, SPOD and db related, File, Web …) and the idea is to cover the full package so that we can switch from and to the two platforms easily. To make it even easier, a neutral package exists that maps to the platform in use. So neutral.Web will automatically map to neko.Web or php.Web.

Some classes have not been ported yet because they extend the Input/Output classes. Those two classes are neko specific but in the haXe 2.0 they will become cross-platform using the new Bytes class. Because I am lazy I will wait for haXe 2.0 to implement them for PHP.