haXe preprocessor
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


To compile requires nothing extra, requires hlex and hllr for boot-strapping.

them simply invoke the makefile, making sure that $HLEX_ROOT and $HLLR_ROOT are correctly set up if boot-strapping.

To execute caxe under windows, you will need to add lib/win to your PATH variable for POSIX threads.

--------------------------------------- SYNTAX

Syntax of caXe is an extension of haXe so all valid haXe code is valid caXe code.

caXe additionaly provides 3 symbolic macro types and an import statement extension.

--------------------------------------- CONCATENATION

Identifier concatenation is performed via the ` binary operator, this will only take effect if the result of the concatenation would be a valid identifier so:

a`b //replaced by ab
a`1 //replaced by a1
1`a //replaced by 1 a (seperate tokens)

multiple instances are ignored

a`````b equivalent to a`b

and noting that this is purely symbolic so whitespace is not important.



1					`2

get's replaced with ab12 as a single identifier

Note, that ` inside of a String for instance will be ignored as it does not constitute a seperate token.

--------------------------------------- STRING LITERALS

Given any piece of caXe code you can create a string literal representing it with the $str(...) command

for instance:

$str(Hello) becomes "Hello"
$str(a+{hi there}) becomes "a+{hi there}"

though you should not expect literal stringifications (haha word) as this is still done symbollicaly and so the output may not represent your exact input, for instance:

	a + {
/* hi */

will also become: "a+{hi there}"

There is no operation to combine strings, though ` may be used as a dual for this purpose at some point in the future if needs be. haXe compiler should do this already anyways!

--------------------------------------- DOC STRINGS

Comments are stripped from caxe code when compiled into haxe; this is generally just fine since the haxe code is not necessarigly meant to be read.

However for things like javadoc comments you can use the !! symbol to enforce caxe to ignore everything which remains on that line and insert it literally into the haxe code.

!! * The Main class!
!! */
class Main {
    !! * Constructing fun.
    !! */
    public function new() {

Note that macro substitution is not performed on the text following the !! and it is kept in purely iteral form.
If macro substitution is required then you can use the (more limited) $doc macro, eg:

$(mixin header(text)
    !! * text
    !! */

becomes the equivalent to:

    !! * text
    !! * hello
    !! */

Noting the additional 'macro' $$ which is replaced by a space character in output to 'massage' caxe into formatting the output code how you want.

--------------------------------------- IMPORT

In haXe as of writing there is no real way to do wildcard imports, caXe provides wildcard imports for all .cx files given as arguments. The syntax is:

$(import package);

which will recursively import all .cx files in the given package. Including:


to import 'all' files visible to caxe.

--------------------------------------- MACROS

caxe has 3 macro types. mixin,expand,define.

A caxe mixin is roughly equivalent to a standard C-style macro, a call to a mixin with a set of arguments is replaced inline with it's expansion.

$(mixin add(a,b) a+b);
add(1,2); //replaced by 1+2;

or with no arguments:

$(mixin hello hi);
hello; //replaced with hi;
hellothere; //remains hellothere, remember caxe is symbolic not textual

or if there is ambiguity in the parsing you may need to add an empty argument list.

$(mixin ehm() trace("ehm"));
ehm; //replaced with trace("ehm")

note that in ehm(); the empty argument list is not swallowed and this would be replaced with trace("ehm")();

zero-argument mixins are more dangerous but can be nice! in nape for instance I redefine many haxe keywords for instance:

$(mixin global inline() #if !NAPE_NO_INLINE $inline #end);

where the $ before inline prevents an infinitely recursive expansion from occuring (strict definitino of $ given later in doc).

An expand macro is equivalent to a mixin, except that rather than the call being replaced with the expansion it is simply removed, and the set of unique expansions throughout the execution of caxe replaces the macro at it's definition.

$(expand unique(x) trace(x););

replaced by:


NOTE: Order is not well define, and:


is also valid output here.

A define macro is syntactic sugar possible using a mixin together with an expand macro where the string concatenation of the arguments and the macro name replace the call.

$(define class Set(T) {

Set(Int); Set(Int); Set(Float);

replaced by:

class Set_Int {}
class Set_Float {}

Set_Int; Set_Int; Set_Float;

noting that:

$(mixin Set(T) genSet(T) Set_`T);
$(expand genSet(T) class Set_`T {

is an equivalent pair of macros functionally.

the define macro finds it's best use when creating generic types/functions where haXe's type system can often be lacking (like having to pass a function reference so that we can construct the generic from within the class etc) of course debugging code becomes somewhat harder since the compilation errors occur after the translation to haxe and not during.

--------------------------------------- ORDER OF EVALUATION

arguments are evaluated in order before the macro is expanded from the inner most depth outwards.

--------------------------------------- SCOPE

All caxe macros are scoped logically with {} and () together with some caxe specific scoping mechanisms explained later ${} and $().

A macro can be given one of 5 scope modifiers:
    - local  [default]
    - file   (macro visible to whole file)
    - global (macro visible to whole file, and the whole of whatever files imports this file)
    - object (macro visible to first logical scope: in normal usage this will correspond to whatever class you are in but beware that more complex use will not work this way)
    - method (macro visible to second logical scope: in normal usage this will correspond to whatever method you are in with same warning)

for example:

    $(mixin add(a,b) a+b);
	$(mixin file sub(a,b) a-b);
    add(a,b); //becomes a+b
	sub(a,b); //becomes a-b
add(a,b); //remains add(a,b)
sub(a,b); //also becoems a-b

------------------------------------- NESTING

macros may be nested with the restriction that an inner macro may not be scoped outwith of it's parent. so realistically you may only nest local macros.

for instance:

$(mixin test(x)
	$(mixin dbl(x) (x)*2);



Note that the inner macro 'x' argument binds in preference to the outer macro 'x' argument.

This can be handy to package macros together under a macro 'package' of sorts. for example:

$(mixin global math(block)

	$(mixin add(a,b) (a+b));
	$(mixin sub(a,b) (a-b));




------------------------------------ ARGUMENT NESTING

Macros can also form part of the arguments to other macros for instance:

$(mixin requires_hello(def)


requires_hello($(mixin hello(x) x*x));



You can also form an anonymous ('ish) macro as follows:

$(mixin apply(x,y) x(y));

apply($(mixin dbl(x) x*2) dbl, 10);



noting that the name of the anonymous macro follows it's definition in the argument.

When using this anonymous form, the local scope is also captured so that the following is possible:

	$(mixin abe(x) x);
	mix($(mixin bee(x) abe(x)) bee);
$(mixin mix(x) x(10));



even though the mix macro itself has no view of the abe macro.
Note that in this example, the eager evaluation of arguments does not apply, and abe(x) in the bee macro is not expanded until the x(10) part of mix has been evaluated.

------------------------------------------- CAXE MACRO SCOPES

caxe provides three additional scoping mechanisms:

$(macros -> code);
${macros -> code);

where 'macros' is a comma delimited list of macro identifiers (including argument count, optional if there are no arguments). This list of macros defines a filter on what macros are visible to the enclosed code.
where $() is a purely virtual, and ${} will actually generate {} in the resulting code.

for example:

$(mixin add(a,b) (a+b));
$(mixin sub(a,b) (a-b));

$(add/2 -> add(a,b)-sub(a,b));



when a mixin takes no arguments, the '/0' in the mixin list is optional.

The third type is purely syntactic sugar:


being equivalent to: