About ZenCode

ZenCode is a programming language intended to be used as scripting language within a larger host application. Thus if you have an application and are looking for a way to safely integrate plugins or user-provided scripts, ZenCode may be for you.

What is ZenCode?

ZenCode is a programming language and software which can be used to provide an application with scripting and/or plugin capabilities. It is intended to run code with fine-tuned control over what it is allowed to do, such that even unknown or untrusted code can be run safely. At the same time, we want to keep it clean, modern, and easy to learn and understand, even by non-professionals.

The name "ZenCode" denotes both the language as well as the runtime systems.

What is it?

What is it not?

ZenCode is created out of dissatisfaction with the scripting languages that are available today. Amongst the languages used, only few can be effectively and easily used as languages for plugins and scripts in my own applications. Javascript, Java and Lua are the most meaningful candidates here, yet I found them hard to use effectively in practice, for a variety of reasons:

ZenCode attempts to address these issues by defining a strongly typed programming language with sufficient flexibility so that it allows to integrate very tightly with its host system. It makes minimal assumptions about the system it runs in, (for instance, it does not assume the existence of a garbage collector), its standard library does not have any functionality to interact with the operating system (no file I/O, for instance) and it provides the host system with a wide range of features to make the life of the scripter as easy as possible:

Designed to be transpiled

Very often, we have little choice in the system we are writing for. If you need an Android application, you'll be writing Java; and if you're programming for iOS, you'll be stuck with Swift. On the browser, it's Javascript, and even in other systems, you may be restricted by the system you are integrating with.

ZenCode, instead, is designed from day one to be transpiled. In fact, as of writing, a native compiler doesn't even exist. You write code in ZenCode, and depending on your target, you can compile to Java or C# bytecode.

Even the standard libraries are broken into small modules, allowing projects to include only what they need. This prevents the need to include a large runtime library just to support programming with ZenCode. This makes it particularly suitable for mobile or web applications where package size is important.

Designed to be safe

Applications can load ZenCode modules and scripts specifying exactly which classes and libraries they are allowed to use. Anything that is not explicitly allowed is blocked. Attempting to use invalid classes or methods will cause a validation error as soon as the module or script is loaded. This allows developers to load scripts or modules from unknown sources with the peace of mind that they will not access resources they are not allowed to. (although they could still consume more memory or processor power than they should, at least they cannot do any permanent harm to the system)

ZenCode doesn't support reflection nor any of the problems it usually represents. Private fields cannot be accessed. Final fields cannot be modified. Access checks are enforced, always. Random pointer access is not possible. Constness cannot be circumvented. Immutable is forever.

In combination with an easy API to load and unload scripts or modules at runtime, this makes it very practical to use ZenCode as scripting or plugin development language, even inside systems not programmed in ZenCode: the code will be translated to whatever language or system the parent process is running, allowing these scripts and modules to load with virtually no overhead. No additional virtual machine or interpreter is involved.

Designed to be robust

Additional language features help to guarantee both security and stability: constness and immutability are enforced and cannot be circumvented. Fields are always private and can only be exposed through getters and setters.

Values cannot be null unless specified otherwise. You can't accidentally pass a null value where one wouldn't be expected - it will error right at the location where the null was passed and not sometime later. This can save a lot of debugging time.

Likewise, values can be destructed in a deterministic manner, even if the underlying system is using a garbage collector. Files will be closed, managed resources will be cleaned up, and you don't have to break your head for it - things work by default. RAII is a perfectly viable pattern in ZenCode.