node package manager




Disclaimer: This is a spare time project not meant to be used in a production environment. Features and syntax are still in flux and will be for quite some time.

The basics

  • part of the curly-brackets family with a syntax similar to Javascript
  • expression focussed syntax (i.e. allows prototype properties to inline further prototypes)
  • block-scoped references
  • syntax-checking parser, compile-time errors for undeclared variables or redeclaration of variables, notices for potential issues (unused references, shadowing, ...)
  • optional parameter-type checks for annotated parameters
  • commonJS-like module structure, resolved and compiled to single file by command-line compiler
  • compiler support for resource-inclusion
  • pretty output (adria compiled by itself, unmodified compiler output with license header, shell-wrapper and external resources merged)

A few language elements

  • proto keyword for prototype creation/inheritance: var Sub = proto (Base) { };
  • func keyword replaces function
  • :: accesses the prototype: MyBase::newFunc = func() { };
  • -> calls the left-hand side constructors right-hand side prototype property into the current context: MyParent->someMethod(...) (would be, ...) in Javascript)
  • advanced default parameters: Listenable::on = func(event, [ [ args = [] ], context = this ], method) { };
  • also supports simple <param> = <value> default parameters and rest parameter: func concat(target, ...items) { }
  • property expression syntax via prop keyword: MyBase::myProp = prop { get: <getter> set: <setter> };
  • parent and self keywords, i.e. parent->constructor( ... );
  • await keyword to wait for asynchronous functions or callback functions and ([...,] # [, ...]) operator (async-wrap): var result = await fs.readFile(name, #); (waits for fs.readFile to invoke the callback passed as second parameter, then returns the value passed to it)
  • extended for/in statement: for (var key, value in object) { }
  • type specific catch blocks, i.e. try { ... } catch (IOException e) { ... } catch (Exception) { ... }
  • modules access other modules by using the require literal, i.e. var Document = require('./document');
  • the export and module statements make module-internal references available for other modules to require
  • parameter annotation syntax with optional runtime-checks: var stackDiff = func(Array stack, Array lastStack, finite minStackLen) { }


  • Install a recent NodeJS version, i.e. apt-get install nodejs
  • npm install -g adria (leave out the global flag -g to install for current user only)
  • adria <input .adria file(s)> -o <output.js>
  • node <output.js> (include --harmony flag to use generators)

Use adria --help for more help.

Getting started

Create a new file main.adria:

var Log = require('./log');
Log::write('hello', 'world');

Create another file log.adria:

module Log = proto {
    write: func(...args) {
        for (var id, arg in args) {
            console.log(id + '' + arg);

Compile to a shell executable file with adria main.adria -o hello.js --shellwrap and run with ./hello.js

root@ubuntuvbox:~/dev/adria/stuff# ./hello.js
0: hello
1: world

In main.adria, require('./log') returns the Log constructor exported by log.adria (as the module). Log::write(...) accesses the constructor's prototype and invokes its write method with the given arguments. write uses the rest parameter syntax to gather all parameters into a new array args and then loops through the array using Adria's extended for-in syntax.

log.adria was not specified at the compiler command line. It was added because it was required by main.adria.

Monitoring mode

Manual recompilation can be avoided by using the --monitor option. In this mode, the compiler will watch the given file arguments and their dependencies for changes and recompile the application as required. For the above example, adria main.adria -o hello.js --shellwrap --monitor would keep hello.js up-to-date while you make changes to main.adria, log.adria or any additional requires you might add.