RatJS

RatJS (Rational Javascript) is a Javascript preprocessor (the name is a reference to ratfor) designed to minimise mental anguish for C programmers that find themselves writing Javascript for one reason or another. It's designed to be fairly minimal and to translate to Javascript in a straightforward manner.

Source (Plan 9 C)

Overview

Expression and statement syntax and semantics is mostly the same as Javascript, but variables and functions can optionally be defined with types, e.g.

int
sum(int a[])
{
    int i, s;

    s = 0;
    for(i = 0; i < a.length; i++)
        s += a[i];
    return s;
}

Types are checked at compile-time and relatively strong typing is enforced, e.g. there are no implicit casts between numbers and strings. Explicit casts can be added with C syntax and the var type shares Javascript's weak typing semantics.

The available types are

Trailing comma is supported in lists; it is not included in the output to minimise interoperability issues.

Struct types

Struct types are defined using C-like syntax

struct Foo {
    int x, y, z;
    string w;
};

Again the name was chosen for mental comfort and it should be remembered these are passed by reference and thus more like pointers to C structures, in particular

Foo f;

f.x = 42;

would be incorrect, as f needs to be initialised first.

Currently a constructor has to be defined manually using

void
Foo(int x)
{
    this.x = 42;
    this.y = 0;
    this.z = 0;
    this.w = "";
}

Instances can then be created using C++-like syntax f = new Foo(42);.

Methods can be defined using the syntax

void
Foo.bar(int z)
{
    this.x += z;
}

Struct literals use the syntax

Foo{x: 0, y: 3, w: "foo"}

There is no support for inheritance at this time.

Map types

Map types provide a different way to think about Javascript objects, i.e. as associative arrays. The syntax is

int foo[string] = {one: 1, two: 2, three: 3};

int z;
string a;
z = foo[a];

Instead of string an enumeration type can be used and [string] and [EnumType] maps can be implicitly interconverted at this time. The use of other types is discouraged.

Enum types

Enum types are true strongly typed enumerations (unlike C) that are implemented using strings, e.g.

enum Color { CRED, CGREEN, CBLUE };
Color c;
c = CRED;

compiles to

var c;
c = "CRED";

Note that unlike some "modern" languages the enum values live in the scope of the enum declaration (like C).

The following are also valid:

enum { CRED, CGREEN, CBLUE } c;
enum Color { CRED, CGREEN, CBLUE } c;

Prototypes

All input files are effectively concatenated and parsed as one unit. The compiler looks ahead for functions (but not variables or types), so, unlike C, function prototypes are unnecessary. They can be used to refer to extern code (including Javascript builtins), e.g.

int string.length;
string string.substr(int, ... int);
extern var undefined;

(... specifies that all further parameters are optional, it's also supported for "native" methods, with the usual Javascript semantics of using undefined as the default). The extern keyword inhibits the generation of a var declaration in the Javascript output.

A declaration of the form

struct Foo;

can be used to support mutually referencing structs.

Closures

Anonymous functions/closures can be expressed using the syntax

abs = int(int x){
    if(x < 0)
        return -x;
    else
        return x;
};

There is a shorter syntax

square = int(int x) return x*x;

which I may at some point extend to allow control statements, such as if.

Javascript arrow syntax is not currently supported but I may add support for that if I add type inference.

Type safety

There is limited type safety as type conversion code is generated only for int, string and enumeration types at this time and the enumeration conversion does not verify that the value is in the correct range.

Foo f;
int i[];
Color c;
string s;

c = (var) f;
i = (var) f;
s = (var) f;

compiles happily to

c = f;
i = String(f);
s = String(f);

which leaves c and i with invalid values.

Consider var to be a "danger type" like void * in C.

Known bugs

Planned features

Unsupported Javascript constructs

(Non-comprehensive list)