JS++ 0.5.2: BSD License, Interfaces, Abstract Classes, Virtual Methods, Non-generic Standard Library Classes

You’ve asked and we’ve listened. JS++ is now licensed under the 3-clause BSD License.

When we first announced 0.5.1 back in March, we introduced bare minimum classes. Specifically, I noted the following class features were unavailable:

  • Generic classes
  • Abstract classes
  • Inner classes
  • Interfaces
  • Virtual methods
  • Custom Conversion Rules as defined in my book, “The JS++ Type System”, Chapter 6.2

Every feature in the above list that isn’t crossed out is now available except the last feature (custom conversion rules) which will be arriving next. In addition, today’s release marks the introduction of the Standard Library. I’m going to briefly introduce the new features.

Update to Hello World

The JS++ Hello World program is now written as:

import System;

Console.log("Hello World");

Notice we no longer have to declare console as external. external is used for importing JavaScript libraries, and since we didn’t have a JS++ console implementation yet, we resorted to using the JavaScript console. However, now that we have a Console class in the Standard Library, it’s no longer a problem.

It is always recommended that you use the Standard Library’s Console class over the external JavaScript console. JS++ will detect if a console is available and will not crash if you try to log to an unavailable console. This can be a problem for web browsers like older versions of Internet Explorer, which are still used heavily in enterprise web applications.

Standard Library

The following Standard Library classes are now available:

  • System.Boolean
  • System.Character
  • System.Console
  • System.Date
  • System.Double
  • System.Exception
  • System.Exceptions
  • System.Integer8
  • System.UInteger8
  • System.Integer16
  • System.UInteger16
  • System.Integer32
  • System.UInteger32
  • System.Math
  • System.Object
  • System.RegExp
  • System.String

Many of the above classes, such as System.String and System.Integer32, are wrapper classes for auto-boxing. Currently, these wrapper classes simply provide a type-safe (and sometimes optimized) version of their JavaScript-equivalent methods. For example:

import System;

string s = "my string";
Console.log(s.replace(/^[a-z]/, string(string match){ return match.toUpperCase(); })); // Prints "My string"

The above example provides the exact same functionality as JavaScript’s String.prototype.replace. However, you get safety guarantees that you wouldn’t get with JavaScript. For example, if you try to call System.String.replace using the wrong arguments:

Console.log(s.replace(1));
[  ERROR  ] JSPPE5023: No overload for `System.String.replace' that takes `1' argument(s) at line 4 char 12 at replace.jspp

Optimizations

Always favor using the JS++ Standard Library over “rolling your own” functions. Consider the following code (which you can run yourself with the latest JS++):

import System;

double t = (new Date).getTime();
string z;
for (int i = 0; i < 5000000; ++i) {
	z += Double.POSITIVE_INFINITY.toString();
}
Console.log((new Date).getTime() - t);

And the nearly equivalent JavaScript code:

var t = (new Date).getTime();
var z = "";
for (var i = 0; i < 5000000; ++i) {
	z += Number.POSITIVE_INFINITY.toString();
}
console.log((new Date).getTime() - t);

JS++ average time: 124.4ms
JavaScript average time: 211ms

In this case, JS++ is roughly 70% faster... for nearly identical code.

You may think JS++ adds overhead (based on perceptions of what fast code may look like), but well-written JS++ will be faster than JavaScript. See my other article on optimization for more details.

Typed Exceptions and Multiple Catch Clauses

JS++ 0.5.2 introduces the System.Exception class and enables you to create your own custom exceptions.

Here's an example:

import System;

class CustomException : System.Exception
{
    CustomException() {
        super();
    }
    CustomException(string message) {
        super(message);
    }
}

try {
    throw new CustomException("This is a custom exception object.");
}
catch(CustomException e) {
    Console.log("Caught CustomException");
}
catch(System.Exception e) {
    Console.log("Caught System.Exception");
}

Variadic Parameters

The latest version of JS++ also introduces variadic parameters, which allow you to supply an arbitrary number of arguments to a function:

import System;

void log(Date date, ...string messages, bool silent) {
    if (silent) return;

    foreach(string message in messages) {
        Console.log(date.toString() + ": " + message);
    }
}

log(new Date(), "1", "2", "3", false);

Interfaces

An interface creates a contract. Methods defined in an interface must be implemented by all inheriting classes. Classes can inherit more than one interface.

According to JS++ naming conventions, interfaces should be prefixed with "I" and should be UpperCamelCase.

import System;

interface IWalkable {
	void walk();
}
interface ITalkable {
	void talk();
}

class Person : IWalkable, ITalkable
{
	void talk() {
		Console.log("Talking...");
	}
	void walk() {
		Console.log("Walking...");
	}
}

Person person = new Person();
person.talk();
person.walk();

Callback Type Parameter Names

Callback types can have parameters. Previously, you could only specify the parameter types for a callback/function type. However, you can now add names for these parameters. While these names cannot be used and have no meaningful effect on the executed code, they improve the readability of the code.

import System;

class Bird
{
	void fly() {
		Console.log("Flying...");
	}
}

void(Bird bird) fly = void(Bird bird) {
	bird.fly();
};
Bird bird = new Bird();
fly(bird);

Removal of 'Convert' Module

We have removed from the Convert module from the latest release. It was always used as a stopgap until we implemented the Standard Library wrapper classes, which provide toString() and other methods.

Bug fix: 'typeof' for internal types

For non-external types, typeof will always return the string "internal".

import System;

int x;
Console.log(typeof x); // "internal"

Virtual Methods

JS++ 0.5.2 introduces the virtual keyword and the override keyword to enable virtual methods on classes.

Virtual methods enable late binding and runtime polymorphism.

class Shape
{
    public virtual double area() {
        return 0;
    }
}
 
class Rectangle : Shape
{
    private int length, width;
 
    public Rectangle(int length, int width) {
        this.length = length;
        this.width = width;
    }
 
    public override double area() {
        return length * width;
    }
}
 
class Triangle : Shape
{
    private int base, height;
 
    public Triangle(int base, int height) {
        this.base = base;
        this.height = height;
    }
 
    public override double area() {
        return (base * height) / 2;
    }
}

Abstract Classes

Use the abstract modifier to create abstract classes and methods.

abstract class Shape
{
    public abstract int area();
}
class Rectangle : Shape
{
    private int length, width;
 
    public override int area() {
        return length * width;
    }
}

Enumerations

Enumerations (enums) can be used to restrict values and write type-safe code:

enum Importance { None, Regular, Critical }
 
Importance errorLevel = Importance.Critical;

The one missing feature...

Sadly, there is still one major missing feature from JS++. The Standard Library does not support System.Array yet because it is a generic class, and generics have not yet been implemented. In the meantime, you can resort to declaring your arrays as var:

var arr = [ 1, 2, 3 ];

BSD License

Last, but not least, JS++ 0.5.2 is the first version of JS++ licensed under the 3-clause BSD License.

The download for JS++ 0.5.2 is available from our home page.

Enjoy JS++!

  • Interesting, I’d like to see the output code from the first example. I’ve reseted my Windows and need to install JS++ again and I’m having a previous DLL issue I fixed earlier: api-ms-win-crt-stdio-l1-1-0.dll

    I’ve tried putting the DLL on both “C:/Windows/System32”, “C:/Windows/SysWow64” and the home JS++ program directory T_T

  • I’m now starting to like the JS++ syntax as I’ve adapted with C++ these days. Anyways, I’d be interesting to see this in action: `class C { public var field; public C() { field = null; } }` into `var C_field = 1; function C() { return [ null ] } }`, this would be an extra optimization too, avoiding obj properties and V8 inline caching.

    • Roger Poon

      We already have that planned in the form of “stack-allocated classes.” (Truly, you cannot control whether you get stack/heap allocation once the code hits the JavaScript VM, but you can at least “guide” the VM by generating optimal code.)

      We don’t optimize solely for V8, and we’ve had extensive discussions about this.

      • That’s kinda incredible… But it looks like the language never said about allocating and freeing classes.

  • Please just one question: Which specific JavaScript version does JS++ extends? I’ve noticed that the compiler requires some statements to be followed by a semicolon; it also puts the empty statements ; on the generated code.

  • Please just more few questions: Which specific JavaScript version does JS++ extends? Does it really require ; after some statements? In addition, it generates empty statements from the source codes.

    Could you check the below prints?

    P.S.: Could not modules be generated in a more abstract way? Why all these unnecessary objets and property acesses when most features are optmizable on compile time, e.g., can be directly referred to?

    Also you’re creating arrays just for a function call… Not every JS implementation may optimize calls like these. (Not sure if it’s with the Hello World example only.)

    https://uploads.disquscdn.com/images/df2e70892aa43fbc3f551d9807ab4ad6a0e3bc97b3f54265854ebcd979abfbdf.png
    http://i.imgur.com/501eK9n.png

    • Anton Rapetov

      Hi, I’m Anton. I am leading engineering for JS++, and I was asked to answer your questions.

      1. JS++ is based on ES3.
      2. Yes, JS++ requires semicolons to be present after all expression statements. Mostly the rules are the same as in languages such as C++, Java, C#. Therefore, in all places where semicolons are optional in JavaScript, they are compulsory in JS++.
      3. Good points about modules and creating unnecessary arrays in some cases. Currently, JS++ is under extensive development, and we are prioritizing some essential features over some optimizations, but we are aware of such cases, and these optimizations will certainly be implemented later.
      4. For your first screenshot, in this case, `Uint8Array` is not a type. It is an object. So you can only use it in an expression, for example in a `new` expression: `(new Uint8Array())`.

    • Roger Poon

      If you can be so kind, can you please ask your Uint8Array question (together with the screenshot) on the JS++ StackOverflow tags?

      I’ve created the tags:

      https://stackoverflow.com/questions/tagged/js%2b%2b
      https://stackoverflow.com/questions/tagged/javascript%2b%2b

      The tags are “js++” and “javascript++”. Please tag with both, but please do not tag with “javascript” for now. As a courtesy, I’ve already asked and answered the question about the ECMAScript specification for you:

      https://stackoverflow.com/questions/45405443/which-version-of-javascript-does-js-extend

      I’m going to endeavor to answer all JS++ questions on Stack Overflow.

      I’ve been answering JS++ questions via email, comments, etc, and it would be nice to have a place to aggregate all the knowledge and answers for future reference and for other users.

      • Sure, I like to do this ! I was just not sure if it was the perfect time.

        • Roger Poon

          Yes, I was concerned about timing too but decided there can never be perfect timing.

          The community should be small and tight-knit for now, and I’m quite happy to keep it that way as the language continues to evolve. It also allows me to answer all relevant questions.