[WIP] A language that aims to be conducive to writing beautiful, effective, maintainable code
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
license.md
readme.md

readme.md

Nirvana

A programming language that's conducive to writing beautiful, effective, maintainable code.

Note: I'm in no way a language-design expert. Nirvana, in large part, is my "toy language". However, I didn't want to make just a toy language, but a language that I would want to use, and perhaps others too. I use javascript the most and in general, enjoy using it. However, I feel that javascript has scope for improvement (even beyond Typescript). You might notice that Nirvana has many elements of javascript—this is the reason.

Table of Contents

Guiding principles

Note: This section is a work in progress

Nirvana's guiding principles borrow some of the aphorisms from the zen of Python. Some of these also align with the concepts in The Pragmatic Programmer, Clean Code, and BaseCode.

Simplicity is the ultimate form of sophistication

  1. Code is writ
  2. Yet, code is read more than it is writ
  3. Explicit is better than implicit
  4. Flat is better than nested
  5. Errors should never pass silently unless explicitly silenced
  6. There should be one—and preferably only one—obvious way to do it
  7. Predictable is better than unpredictable. Hence, consistency matters.
  8. Be strict, but don't restrict

Status of this project

Nirvana is in what I like to call "pre-semver", that is, it is an idea right off my head (anything may change at any time). At the moment, the language spec in itself is far from finalised, let alone tools such as compilers/interpreters, linters etc.

Debate, discussion about elements of language/syntax and contributions in any other form are warmly welcome 🙏.

Features

  • Static types
  • The "unpredictable" type
  • Asynchronous functions
  • Anonymous/lambda functions
  • Classes with support for OOP
  • Easy-to-use support for modules

Syntax

Comments

// line comment
/*
 * block comments
 */
/**
 * <doc comments>
 */

Datatypes

Booleans

bool isValid = true;

Strings

string example = "hello world";
string anotherExample = 'hello world';

Numbers

int x = 1;
float x = 3.21;

Regex

RegEx email = /[a-z0-9_-.]+@.+\.[a-z]+/ig;

Ranges

for (int i in 1..10) {
    out.println(i);
}

Lists

int[...] list = [1, 2, 3, ...];
int[...] anotherList = [...];

list.push(5);
list.peek();
list.pop();

list[0] = 4;

Arrays

int[] array = [1, 2, 3, 4, 5];
int[] anotherArray = new int[15];

array[2] = 4;
int[] newArray = array[2..4];

Maps

TODO

Unpredictable

* variable = "string";
variable = 42;
variable = new Item();

Note: Use sparingly and with caution. A kitten dies somewhere each time you use this type without a very good reason.

Constants

const float pi = 3.1416;

Arithmetic

int x;

x = 3 + 5;
x = 3 - 5;
x = 3 * 5;
x = 3 / 5;
x = 3 ** 5;
x = 3 % 5;

If I eventually settle on not supporting bitwise operators (this too is up for debate), I'll switch to 3 ^ 5 rather than 3 ** 5.

Comparison

Eventually, I plan on supporting unicode characters like “≥”, but I'm unsure about this (since it will be two ways of doing the same thing).

bool x;

x = 3 == 4;
x = 3 != 4;
x = 3 < 4;
x = 3 > 4;
x = 3 <= 4;
x = 3 >= 4;

Logical Operators

bool isOdd = true;
bool isEven = not isOdd;
bool isAlsoEven = not(isOdd);  // logical operators support parentheses grouping
                               // which might lead to function-like appearance
bool x;

x = isOdd and isEven;
x = isOdd or isEven;

If-else

if (booleanExpression) {
    // do stuff
} else if (booleanExpression) {
    // do other stuff
} else {
    // do something else
}

Throwing errors

	throw new Error();

The in-built Error class can be extended.

class HttpError extends Error {}

Try-catch-finally

try {
    // dubious stuff
} catch (Error err) {
    // error handling
} finally {
    // do this stuff regardless
}

For-in

int[] array = [1, 2, 3, 4];

for (int element in array) {
    out.println(element);
}
for (int num in 1..10) {
    out.println(num);
}

Traditional for

for (int x = 0; x < 10; x++) {
    out.println(num);
}

While

int i = 10;
while (i >= 0) {
    out.println(i--);
}

Do-while

int i = 10;
do {
    out.println(i--)
} while (i >= 0);

Functions

int basic (int a, int b) {
    // body
    return 42;
}

Default parameters

int defaultParams (int a, int b = 2) {}

Overloading

int example (int a, int b) {}
int example (int a, int b, int c) {}
string example (string a, int b) {}

Rest parameters

int restParams (int ...values) {}

"unpredictable" return type

* unpredictableReturn () {}

Async functions

TODO

Classes

class Example {
    int a = 24;
    string x = "hello";

    Example() {} // constructor

    float example (int b) {}
}

Encapsulation

Class properties and methods can be made private simply by prefixing their identifiers with an underscore (_). While this implicit approach to access control goes against nirvana's principle of “explicit is better than implicit”, the dangling underscore is a common convention. One of the biggest reasons for doing so is so that each time a private property is accessed from within a class, it is obvious that the property is private.

class Example {
    int _a = 24;
    string x = "hello";

    float _example () {}
    int anExample () {}
}

Static

class Example {
    static a = 42;
    static float example () {}
}

Getters and Setters

class Example {
    get prop () {}
    set prop (string a) {}
}

Example a = new Example();
out.println(a.prop);
a.prop = "hello";

Import

import Object from "lib/Object.nrv";
import "lib/sideEffectsOnly.nrv";
import something, SomethingElse from "lib/stuff.nrv";
import Stuff from "module";

Export

export Object;
export something, SomethingElse;
export "lib/example.nrv"; // may be useful in libraries

Design by Contract

Nirvana supports DBC out of the box.

  • Precondition
  • Postcondition
  • Invariants

Borrowing an example from Pragmatic Programmer,

/**
  * @invariant
  * for (Node n in elements()) {
  *     if (n.prev() != null) {
  *         assert(n.value().compareTo(n.prev().value()) > 0);
  *     }
  * }
  */

/**
  * @pre this.contains(node) == false
  * @post this.contains(node) == true
  */
void insertNode(Node node) {
    // ...
}

Roadmap

All software building steps listed below refer to bringing that software to version 0.1.0. All of the following are tentative and approximate.

  1. Write language spec
  2. Write standard library spec
  3. Write a compiler/interpreter (haven't decided which yet)
  4. Write a linter
  5. Write a testing suite
  6. Write a documentation generator
  7. Create a package repository (similar to npmjs.com) and installation system
  8. Write editor extensions

Eventually, this repo will move into the nirvana-lang organisation, possibly with the name "docs".

License

The contents of this repository are licensed under The GNU General Public License v3.0. Most of Nirvana’s future repositories will also be licensed under GPLv3.