A few approaches to utilize Haxe and its targets

Haxe is a programming language that can be transpiled to many other languages thanks to the powerful Haxe compiler. Because of this very nature, Haxe is really versatile and the Haxe developer spectrum is really wide. Developers use Haxe to develop games, web apps, mobile apps, desktop apps, servers, tools, etc. Therefore, when authoring a Haxe library, ideally it should cover as many targets as possible. So that everyone would be able to use it. Here I would like to list a few approaches to utilize Haxe and its targets to write truly cross-target code, using a work-in-progress Big Integer library I have been working on recently.

Make every Haxe target work for you

Silver bullet: Write the entire implementation in Haxe

When code is written in pure Haxe, it is guaranteed to work on every targets (provided that it doesn’t use any target-specific APIs). Result-wise, this is the ideal solution. Due to the single code base, we can guarantee the program behaviour is consistent across targets. Also, this approach doesn’t has any external dependency, meaning that Haxe user will only need to install the code via haxelib (the Haxe library manager). Then the compiled program will just work, without additional setup.

However, this approach is very time-consuming. I am using the BigInteger.js library as the reference implementation. It contains about 1500 lines of code and it is utilizing a lot of JS-specific tricks. That means I can’t easily port it to Haxe without many changes. It would probably cost me weeks to completely port it to Haxe. Someone would want to do this ultimately. But I want to kickstart quickly in a hope that it would facilitate a Haxe RSA implementation.

Exploit the targets

Instead of writing the whole thing from scratch with Haxe. I decided to harvest the strength of each target. This is a much simpler approach yet very pragmatic. In order to do that, I first defined an API, then implemented the details for each target, separately. For example, for my Big Integer library, it would have a constructor plus a set of arithmetic operations. A simplified version would look like the following. (Note that I am using abstract instead of interface. Because it supports implicit cats, operator overload and doesn’t have dynamic dispatch overhead which is present in interface)

abstract BigInt(Impl) {
  // store commonly used values as a static var
  public static final ONE:BigInt; 

  // create a big int from string
  @:from
  public inline static function fromString(v:String):BIgInt; 

  // max of two values
  public inline static function max(a:BigInt, b:BigInt):BigInt; 

  // addition, with operator overload
  @:(A+B) public inline function add(other:BigInt):BigInt; 

  // string representation
  public inline function toString():String; 
}

After defining the API, the next thing is the implementations. There are a few ways to do so depending on the target language’s characteristics, feature set and ecosystem. The following is an excerpt from the actual work I have done. Full versions can be found in the project repo.

Python: By default integer has unlimited size

Since python’s integer is “big integer” already, I can simply map all the API operations to standard integer operations. It is going to work right out of the box.

abstract Impl(Int) from Int to Int {
  public static final ONE:Impl = 1;
  public static inline function fromString(v:String):Impl
    return UBuiltins.int(v);
  public inline static function max(a:Impl, b:Impl):Impl
    return a > b ? a : b;
  public inline function add(other:Impl):Impl
    return this + other;
  public inline function toString():String
    return UBuiltins.str(this);
}

(Note how the implementation uses standard operators and builtin methods.)

Java: BigInteger included in standard library

Java has the java.math.BigInteger class, so I could utilize it. It also works out of the box.

import java.math.BigInteger as Native;
abstract Impl(Native) from Native to Native {
  public static final ONE:Impl = Native.ONE;
  public static inline function fromString(v:String):Impl
    return new Native(v);
  public inline static function max(a:Impl, b:Impl):Impl
    return a.max(b);
  public inline function add(other:Impl):Impl
    return this.add(other);
  public inline function toString():String
    return this.toString();
}

(Note how the implementation uses the API provided by the native Java BigInteger class.)

Javascript: Use the BigInteger.js library

On newest browsers there is a native BigInt type. But for best compatibility I chose to use a library. (and the library will utilize the native type when it is available).

abstract Impl(Native) from Native to Native {
  public static final ONE:Impl = Native.one;
  public static inline function fromString(v:String):Impl
    return new Native(v); 
  public inline static function max(a:Impl, b:Impl):Impl
    return Native.max(a, b); 
  public inline function add(other:Impl):Impl
    return this.add(other); 
  public inline function toString():String
    return this.toString(); 
}

@:jsRequire('big-integer')
private extern class Native {
  static var one:Native;
  function new(v:Any);
  static function max(a:Any, b:Any):Native;
  function add(number:Any):Native;
  function toString():String;
}

(Note how the implementation uses the library’s API)

A side note for js: Normally, in order to use js libraries, one would need a package manager such as npm or yarn. But thanks to Juraj‘s awesome library embed-js, we can instruct the Haxe compiler to download the library’s js code and embed it into the Haxe-generated js output at compile time. Making it work out of the box as well.

PHP: Use GMP extension

On PHP there is a native extension that supports big integer operations called GMP. Setting it up isn’t too hard. Just download the binary and enable the extension in php.ini.

abstract Impl(Native) from Native to Native {
  public static final ONE:Impl = fromString('1');
  public static inline function fromString(v:String):Impl
    return Gmp.gmp_init(v);
  public inline static function max(a:Impl, b:Impl):Impl
    return Gmp.gmp_cmp(a, b) > 0 ? a : b;
  public inline function add(other:Impl):Impl 
    return Gmp.gmp_add(this, other);
  public inline function toString():String
    return Gmp.gmp_strval(this);
}

@:phpGlobal
extern class Gmp {
  static function gmp_add(a:Gmp, b:Gmp):Gmp;
  static function gmp_cmp(a:Gmp, b:Gmp):Int;
  static function gmp_init(n:Any, ?b:Any):Gmp;
  static function gmp_strval(a:Gmp):php.NativeString;
}

(Note that this is very similar to Java except the additional setup)

Conclusion

I found this “exploit the targets” approach works very well. It is simple and effective. More importantly, it ensured extensibility because the interface definition itself is target-agnostic. For additional targets to be supported, one only needs to implement the interface accordingly, may it be a pure Haxe implementation or implemented via some libraries in the target’s ecosystem. Anyway I reassure the ideal approach would be a pure Haxe implementation. But before we have time do so this would be a pretty decent and practical compromise.

In fact there are quite a few libraries in the wild already using this method. Here are some of them: tink_http, tink_io, tink_tcp, why-ble, why-fs

This topic is pretty unique to Haxe because of it multi-target nature. Hopefully more libraries would be written in this way so that it benefits the Haxe ecosystem more!

Apply @:genericBuild on a function in Haxe

Acknowledgement: The solution about applying @:genericBuild on functions is actually inspired by the haxetink libraries, in particular tink_json.

@:genericBuild in a nutshell

In Haxe, @:genericBuild is a metadata that tags a class to be built with a macro, which is invoked for every occurrence of the class.

chameleon-226287_640

// ThreeDArray.hx
@:genericBuild(MyMacro.build())
class ThreeDArray<T> {}

// MyMacro.hx
class MyMacro {
  public static function build() {
    switch haxe.macro.Context.getLocalType() {
      case TInst(_, [p]):
        var complexType = haxe.macro.TypeTools.toComplexType(p);
        return macro:Array<Array<Array<$complexType>>>;
      default: throw 'assert'; // technically unreachable
    }
  }
}

// Then in somewhere:
var my3dIntArray:ThreeDArray<Int>;
var my3dStringArray:ThreeDArray<String>;
// etc...

Continue reading Apply @:genericBuild on a function in Haxe

Method Overloading achieved with Abstracts in Haxe

Method Overloading in general

In this post I am going to introduce “method overloading” in the Haxe programming language. In general, method overloading means that a collection of functions with different type signatures, that share the same name. For example in Java, one would write the following code:

public void foo(String bar) { /* body ... */ }
public void foo(String[] bars) { /* body ... */ }

Then you can call either foo("my string") or foo(new String[]{"my", "string"}).

method overloading with haxe abstracts

Continue reading Method Overloading achieved with Abstracts in Haxe

Haxe: Running @:build macro on typedefs

As at 3.2.1, Haxe does not support @:build macros over a typedef. But I just discovered a trick to do that. That utilizes a @:genericBuild macro. Well, honestly, this is not truly a build macro because the type is read-only. i.e. you can’t add or remove or alter fields of the original type. But you can declare a new type based on that and return it as the type for the call site. I found it quite useful for my use case because I would like to make a copy of the typedef in some fashion.

Continue reading Haxe: Running @:build macro on typedefs

Haxe macro: copying expressions from another Type

I was playing around inspecting the contents of other Types through haxe macro when I found that I can copy expressions from another type very easily. I think I should write it down as a note for myself.

A possibly interesting use-case is that Haxe doesn’t inline your function even you marked it as inline, if you try to store the function in a variable.

static function main() {
  var t = test; // outputs `var t = test;` instead of `var t = function() {trace("test");}`
  t();
}

static inline function test() trace("test");

However, with the following simple macro trick, we can assign a function to a variable “inlined”

Continue reading Haxe macro: copying expressions from another Type

Transform js-style callback to Future with Haxe macro

EDIT (4 July 2016): A newer solution for this problem can be found at: https://github.com/kevinresol/futurize

Haxe macro is very powerful and it is really good at eliminating boiler-plate codes.

In the past 2 months I have been working on a web server using haxe/nodejs + ufront + mongoose (through js-kit). Since ufront supports async operations through Futures while mongoose uses js-style function callbacks, I have to write a lot of bolier-plate codes to convert the latter to the former, like this:

However, it is very cumbersome. If I have more than 100 database call like that, I have to write that code 100 times. Continue reading Transform js-style callback to Future with Haxe macro

How to write jQuery plugins in Haxe

This blog post recorded how I came up with the idea. You may jump to the GitHub repo directly, example usage is written there.

Everthing started from an old jQuery plugin

Recently I started to use Haxe as my primary programming language. I have always been thinking about what I can do with this modern language. Until I dug out an old jQuery plugin, which I wrote several years ago, while I was cleaning up some old files in my server. I remembered that it wasn’t easy to develop in javascript. It is because at that time there was no (or at least I was not aware of any) decent IDE for javascript. Even with the powerful debugger FireBug, which just began to gain popularity at that time, I still found it painful to debug javascript programs. Therefore I have stopped writing in javascript since then. Looking at the plugin’s forgotten to-do list and the unfinished next-version, I decided to find a way writing jQuery plugins (again) in Haxe.

Here is my goal to be done in Haxe:

  1. Register a function as a jQuery plugin by adding it to the jQuery.fn object
  2. Able to access the “this” object within the plugin function as in vanilla javascript
  3. The javascript output should be as simple and clean as possible
  4. Most important: Leverage Haxe’s feature such as Macros, Code-Completion, Compiler Checks to write a decent plugin

Continue reading How to write jQuery plugins in Haxe

Haxe SPOD: Specifying a unique field

Haxe has a very nice library called SPOD Macros which allows us to manipulate database tables as strictly-typed objects instead of dealing with the plain-text SQL commands and the clumsy result sets/arrays of untyped row objects.

The Problem

As at Haxe 3.0.1, SPOD does not provide a compile-time solution (I mean metadata like @:table and @:relation) to specify a field to be unique. One of the solution is to first create the table in Haxe, then use a database management tool such as phpMyAdmin to configure the column to be unique. However, I would like to do this in my Haxe code, after all we are programmers!

Continue reading Haxe SPOD: Specifying a unique field