jspp: Too good to be true === --- Opening words --- *I'm not some cool journalist and this article is just my thoughts and emotions typed into .md file.* I was browsing some [awesome lists](https://github.com/topics/awesome) on github and stumbled upon a big list of [programming languages](https://github.com/ChessMax/awesome-programming-languages) where I accidently found [jspp](https://www.onux.com/jspp/), an intriguing language that promises to be so much and so safe and compiles into plain js. I was instantly drawn to it, since I'm always in search for different languages for different things. D for general programming, (unknown for now, coz I don't like c#) for game development and now jspp for web. --- My background --- [You can skip this part if you want to read only about the language itself.](#Comparison) To explain some of my point and justify why I see some things way I see I need to tell what I've used and know. My journey starts with small program called GameMaker 8. I tried programming before that, but gm8 marks my first real programming experience. GameMaker 8 and all subsequent releases (GameMaker: Studio, Game Maker Studio 2 and now Game Maker) use language **gml** that is very similar in syntax to javascript. Next was, surprisingly, **Java**. Lovely language but it's such a pain developing with it and it's so heavy on resources, so we weren't able to become friends. After java came **c/c++** in which I made a small cli roguelike to play on my phone, but not more. Imo they're derelict and there are better choices. And then, finally, **javascript**. God bless this language hence it's dumb. I even tried using typescript, but it quickly became incredibly annoying and I quit back to plain js. Then I decided to try Unity and Godot, which wasn't really a lucky encounter, but I came back to them some time after and found out that I kind of like Godot in combination with **c#** (which is **fine** language) because: **Python**. Oh, where do I start with python. In my opinion it's absolutely hideous language. Tabs/spaces as code blocks? Dynamic typing? c_style_case? Taking all control from programmer to make it easier for them? I'm not saying it's bad language, it's rather opposite, for Data Science, in which it's mostly used, it's a perfect language. But for me, no thank you. Used it to do some things and also to configure qtile. And guess what, **GDScript**. Python but godot-flavored. Nothing against it, but I don't like it and use it only when c# is lacking functionality or to change addons I use. **D**. I wouldn't say much, but this is the language I'd choose over anything. **Haxe**. It's just scripting c#. No, thank you. **Dart**. Now we're talking. That's the language that might rule the GameDev side IF there will be bindings so not right now. **Go, Rust, Scala, Swift, Ruby** - Basically a python with different syntax. Not my cup of tea. And **jspp**. Finally, a web language of my dreams. JS but typed, with classes and smart and so much more. *A side note. My choice of languages right now is: D for anything I can use it with, Dart/C# for gamedev and jspp/JS for web.* --- Comparison --- Let's talk web! Can we talk web? I'm dying to talk about the web! *Yea, smartass, you talking how much you "know" but what about jspp?* **JavaScript**. The absolute insanity of a language that people thought is a good idea. It's perfect to do anything fast, cheap and dirty. It's welcoming you to the world of NaN, Undefined Behavior and "Cannot read property of null". But what we have as alternative then? **TypeScript**. Microsofts attempt to make js typed and less frustrating. It's problem is fact that it doesn't eliminate any js errors and just lets them happen. Plus that dumb `var name: type` style of declaration. **CoffeeScript**. A language for lazy people. Why? Who knows, but I certainly know that it isn't serious. **Clojure**. Want everything be a closure? Like how callback hell looks? That's a language for you. **Elm**. Imagine python, but for web. Me and python are rivals and so we move on. **Dart**. Now we'll stop for a bit longer. What is dart? Dart is a strongly typed language, with classes and smart and so much more... but? To explain dart I need to explain two things. dart2js which is a small transpiler that converts dart code into javascript and Flutter which is google sdk for making apps in any platform. Both of them are viable for web, but dart2js produces such a bloated js that spans across thousand of lines just to make console say "hello world" and Flutter is not suitable for me hence it's for making apps, and for that I have D. And so we come to **jspp**. So, why it's *the* choice? --- Features --- Citing official jspp website: *"jspp brings the first sound optional type system for "million-line scale" application complexities. With near-instant compile times, it will feel like you're still writing dynamic code"* And it's true. jspp is strongly typed language that compiles into plain js almost instantly, eliminates 99% of type errors, has classes you usually see in big boy languages like c#, java and d. Big point of jspp is type safety, which it delivers. To explain more, let's dive right into source code. Let's say you declare a simple int. ``` int i = 0; ``` jspp compiler is going to produce type safe declaration that wouldn't make sense at first, but it will later. ``` var i = 0 | 0; ``` So, what is this `| 0` there? It's jspp way for providing type safety for you. Full list is: ``` var dnum = $(number) | 0; // declaring number var dstr = "$(string)"; // declaring string var dbol = $(boolean); // declaring bool, which is always "true" or "false var num = +n; // using number variable var str = n; // using string variable var bol = !!n; // using bool variable ``` A quite smart way to make you know that everything is going to be safe and sound in all meanings of it. Now, the interesting part of it all is *external* type, which can be either a `function` or a `var`. Both of them can be declared and used in jspp to provide interchangeability with plain js code. If you want to use some library from js you declare `external $;` at top of script, which allows jspp to use this symbol, but be cautious since jspp doesn't check external symbols and they might give you undefined behavior or "property of null" errors. On a side note, have you ever tried to use typescript typed variables with javascript untyped variables? It's hell. But how do use include your own libraries then? Simple, you do `import ModuleName;` to import module `module ModuleName { /* code */ }` that you declared in another file. This allows for incredibly simple symbol import even if you use libraries made by someone else, you just need to include them in your file list when you compiling the code. Also jspp has a feature that plain js doesn't has. Generics. Yes, they're not fully ready to say for now, but about that later. Another point to jspp is that opposing to typescript it conceals it's code in simple expression `!function(){ /* code */ }();`only purpose of which is to hide typed properties so nothing can change then. But how do you use jspp code in js code then? [This article](https://www.onux.com/jspp/blog/writing-javascript-libs-using-jspp/) explains it in somewhat simple words and I recommend to look at compiled code after to see what's going on. *Ok, but what if I want to do some math, or string manipulation. Do I need to declare those functions externals?* No, jspp has a nice standard lib called *System* in which there are methods for all types (from bool, string, char & int8 to int32, float & double). Some methods might be not what you think, for example `substring` that conflicts with js substring, but in that case just take a look at [documentation](https://www.onux.com/jspp/docs). Also in System library there are two interesting things. First is containers, which cover Arrays, Dictionaries, Queue and Stacks. Second is not in a System library, but library itself called *Externals*. Externals library exposes three types of symbols of your choice. *Externals.JS* exposes all ECMA 3 symbols, *Externals.DOM* exposes all DOM symbols (such as *window*, *document* and so on) and *Externals.Time* exposes all timeout and interval methods. You can actually write such a library yourself. For example, let's say we want to expose jQuery methods to jspp. ``` module Externals.JQuery { external $, jQuery; } ``` And that's all you need to do to have it all exposed. --- What's wrong --- But like all languages jspp has it's flaws and there're a lot of them. ***This article is written as of jspp compiler version 0.10.0, which is not final and next two sections must be read with caution, since some features are still a subject to change. In addition to that jspp is still feature-wise in ECMA 3.*** Have you ever tried declaring functions *after* you called them. If so then this called hoisting and this is **not** something jspp has right now. Yes js supports it now and yes jspp will be having it, but for now this is a huge thing to consider. jspp has generics, but all they can do is to be a uniformed typed container for something. They're not powerful in any way, there's no generic method overloading and you can't check type T in runtime. So yea, for now if you want you can have something like this, but not much more then that: ``` class Vector2 { public T x; public T y; public Vector2(T _x, T _y) { x = _x; y = _y; } } ``` Next thing comes from javascript and I personally don't understand why it exists. Existent types. c# has a feature where you can declare nullable types as `int? nullable` and jspp follows this feature, but it also introduces new type of type, existent, which you can declare as `int+ existent`. Why it exists? Because javascript has two "states" of variable. If variable was declared but not assigned value, it's undefined. And if variable has empty value then it's null. The problem arises when we look at other languages and none of them have this kind of *undefined* value. All of them are either initialised as *null* or with default value. And jspp tries to solve that by introducing this exact existent type, which leads to more confusion where you try to, for example, access arrays. So, recap, existent types are way jspp solving undefined value. But the thing is, there is already a way that exists and it's nullables. In my opinion existent type is pointless and better to make it same as null, but who am I to judge. Next dish we're not going to have is async. As for now async is not implemented, yet there are promises to do it as [*suspend-next*](https://gist.github.com/rogerpoon/205d7b2d1d01b07764882817db3f8085), which is much more pleasing solution then js async-await. It's totally understandable since jspp is still in ecma3 feature-wise but as for now it's not ready for use with something like NeutralinoJS which is async heavy. When someone comes into programming and starts to touch languages like c, java, c#, d, c++, etc.. one of first things they learn is that `'` is for characters, `"` is for strings and sometimes ``` is for multiline strings. jspp throws all this out of a window. Now `'` and `"` are for strings, ``` for characters and `"""` is for multiline strings. I know it's a small complaint and it's to maintain compatibility between js and jspp, **but** now js has template strings which are defined with ```, which makes it more confusing then ever. Imports in modules is another small questionable part. Documentation states that if you want your imports be imported with modules you include import statement within module body, but all of other programmer senses tell you that this isn't right since if you declare something within the scope it stays within the scope and so another confusion is here. Another not really working thing is inheritance. Yes, there are keywords like `descend` and `ascend` which are like childOf and parentOf respectively. Sadly right not in some cases you're better off just declaring interface and using it as parent type. And I hope this is going to be fixed later. jspp exports to js aren't clear to be honest or they just aren't clearly explained. Article that I've linked in features part goes a long way to say that to export something from jspp to js you need to just give *global* an object. I.e: ``` external global; global.myFunc = function() { /* code */ }; // or global.myClass = function() { return { myFunc: function() {}, myProp: 5 }; }; ``` And since we talking functions, another missing feature is *lambda* functions, aka `() => {}` and default values for arguments, aka `void exec(int def = 0) {}`. It's just not yet there. Another big thing that might throw you off is poor editor support. Almost all editors and some web highlighters have some sort of plugin for jspp, but only one that is currently usable is Sublime Text. Everything else has almost only basic syntax highlight. And there's no language server either too, so no autocompletion, no scanning, no definitions, no IntelliSense. Also jspp is yet to have [Reflections](https://en.wikipedia.org/wiki/Reflective_programming) or any close-to-meta programming at all. Last thing I would mention is documentation itself. It's incredible, simple and with combination with long tutorial that explains many features of language it gives almost full perspective on the language. **But**.. it's not full and in some places it describes things that yet to exists. For now missing features I know are: - Context (can be found only when you try using *this* as javascript *this* in callbacks) - Ascend, Descend (can be found in tutorial) And from features that yet to exists is *long* type. --- My proposals --- Now, this is important part in why I think that jspp is not ready yet, because those things are important in making a good programming experience. This section is continuation of *What's wrong* and will go in more extend of things that are missing of not fully implemented in my opinion. Also this section will go deep with examples since it's proposals and it's best if there is some code to look at. **Defining externals & External classes**: Currently you can only define external symbol which is assumed to be a variable or function and there's no assumed syntax / type of said symbol. I propose this syntax to define external symbols or classes: ``` // Variables // external symbol: type; external counter: int; // Functions // external symbol: functionType; external adder: int(int a, int b); // Classes // external class: classInterface|sourceClass external Obj: System.Object; external Worker: IWorker; external ServiceWorker: MyServiceWorker; ``` If in case of variables and functions it's clear what types are in classes I need to explain a bit more. If external class is defined by giving an interface then it's assumed to have interface methods with given function signature. If external class is defined by giving a class then it's effectively bound with internal class methods and properties. In more detail external class definitions are nothing more then a way to internally bind external object and must be eliminated with DCE if not used in source otherwise. Defining external class properties with this logic is only possible if defining it with internal class because interface cannot define members. So external class members can only be assumed with internal class definition. If external class is defined using System.Object then no properties or methods are definitely assumed and any symbols are allowed in use with it. This proposal is mainly a feature for programmer comfort and more type safety for compiler. **typedef / alias** Ability to declare aliases for internal symbols without giving user too much control (like with c style macro). This feature is not required, but would be incredibly powerful if combined with generics. **Generics** Currently generics are lacking in features and usable only as containers. My proposal would rely on having Reflection and would ask for closer inspection of generic types (aka `T` in `generic<T>()` ). **static if / #ifdef** This feature might not be greatest, but if implemented correctly this might be one the biggest metaprogramming features. ``` class MyClass { static if(typeid T == typeid int) {     int intFunc() {} } else {     void nonIntFunc() {}     } } ``` **Operator overloading** Allow programmer to overload operators. If this feature currently exists in any way then I'm certainly missing it in docs. ``` // either go c++ way of: int operator+(int a, int b) {} // or go d way of: int opBinary(string op, int right) {} ``` **Method extensions** Allow programmer to define custom methods for certain types. There are several ways languages do that. ``` // c# class IntExtension { int Adder(this int a, int b) { return a + b; } } // d // in d any method is already an extension method and can be executed // as myIntVar.adder(4); int adder(int a, int b) { return a + b; } ``` Since jspp types are internally a class I propose this syntax: ``` // injectMethod(type, methodName, delegate); injectMethod(System.Int, "adder", int(int a, int b) {return a + b;}); ``` And to bind it into plain js: ``` Object.defineProperty(System.Int, methodName, { value: delegate, writable: false }); ``` **Optional arguments** Allow "default" arguments defined by providing default value for argument which will make argument optional `int adder(int a, int b = 1)`. **Allow const as mutable final** Speaks itself. **Module import scope overhaul** Allow programmer to define visibility for imports by providing visibility modifiers (i.e *private*, *public*). ``` private import System; // only visible in module public import System; // visible in module and files that import this module import System; // private by default ``` **Overall import overhaul / stdlib overhaul** Returning to method extensions, I propose to have stdlib methods be method extensions and static methods rather then System.%Type% methods. **String literals** I propose to change string and character literals to their normal counterparts. There's no point in keeping consistence with javascript anymore since now it's uses backticks as multiline strings and it'd be much easier to associate string and character literals with those which are used in most languages. **Structures** As an alias to classes. **ECMA-Next** Bring jspp to current state of ECMAScript, which includes: - Function hoisting - Lambda functions - ...object syntax - Change internal ?? to ES2020 ?? - etc... **Nullables** Next one is treat all undefined as null to eliminate confusion between types. Out of bounds arrays must throw out of bounds otherwise `?.` becomes the only array accessor. **jspp to js export** This is more of a documentation proposal, but is important one. And proposal is to add it to docs and explain it in simple words. **Breaking changes** Version 1.0 must bring breaking changes in favor of better user experience and better code compilation. Otherwise the language is going to stagnate on it's old ground. --- Closing remarks --- Overall jspp is such a promising language and there's much more good things then I described, but what I said is my perspective as a developer translating my website from js to jspp. And in meantime I was finding more and more small things that were annoying, but haven't prevented me from finishing. Besides, almost all code of [this](https://al1-ce.dev) website you're reading it on (aside from console code which is asynchronous) is written is jspp and I'm happy with it. If you want to try out jspp then do it, head to [jspp](https://www.onux.com/jspp/) website, download compiler and follow along official tutorial. If you feel like it's your language then go for it even if there's that ^ much not-so-finished things. Thank you for reading and see you around then!