Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/Zolang/Zolang

A programming language for generating code for multiple platforms
https://github.com/Zolang/Zolang

Last synced: 7 days ago
JSON representation

A programming language for generating code for multiple platforms

Awesome Lists containing this project

README

        


Zolang β€’
ZolangTemplates β€’
Zolang IDE

![Zolang Logo](https://github.com/Zolang/Zolang/blob/master/Images/zolang-banner.png "Zolang logo")


Swift
Platforms
MIT

Table of Contents

[What is it?](#What)

- [What Zolang is Not](#IsNot)

[Documentation](#Docs)

- [Installation](#Install)
- [Getting Started](#GetStarted)
- [Example](#Example)
- [Language Overview](#Overview)
- [Types](#Types)
- [Operators](#Operators)
- [Comments](#Comments)
- [Models](#Models)
- [Functions](#Functions)
- [Arithmetic](#Arithmetic)
- [Loops](#Loops)
- [Metaprogramming](#Metaprogramming)

[Roadmap](#Roadmap)

[Why Zolang?](#Why)

[Name](#Name)

[License](#License)

# Zolang
> A lightweight frontend for virtually any general purpose programming language.


## What is it?

Zolang is a programming language with capabilities that make it transpilable to virtually any other programming language.

Zolang does this by offloading code generation to its users through [Stencil (template language)](https://stencil.fuller.li/en/latest/) specification files.

Theoretically though, these (`.stencil`) specification files could make Zolang output any kind of text. Making the language a very useful code generation tool and a decent lightweight alternative to many cross-platform frameworks.


### What Zolang is Not
Zolang is not a general purpose programming language and probably won't have support for standard library functionalities in the forseeable future. This is because Zolang uses a templating language for compilation, which is not the expected usage of such a language, and becomes slow quite quickly, limiting the amount of code feasable for Zolang development.


## Documentation


### Installation

#### MacOS

```
curl -LO https://github.com/Zolang/Zolang/releases/download/0.1.19/zolang
mv zolang /usr/local/bin/
chmod +x /usr/local/bin/zolang
```

#### Linux & Mac (Build From Source)

At the time of writing there is a bug in Swift on Linux that prevents me from providing working build for Linux so if you're running on Linux you will (for now) have to have Swift installed ([Download Swift](https://swift.org/download/#releases)) and simply build from source.

```
git clone https://github.com/Zolang/Zolang
cd Zolang
swift build -c release
cd .build/release
cp -f Zolang /usr/local/bin/zolang
```

#### Verify installation

```
zolang
```


### Getting Started

#### Setting up development environment

Zolang is best with Visual Studio Code using the [zolang-ide](https://marketplace.visualstudio.com/items?itemName=valdirunars.zolang-ide) extension

#### Initializing Project

If you don't have an existing project start by creating a project folder and navigate to it

```
mkdir MyZolangProject
cd MyZolangProject
```

Then initialize the project

```
zolang init
```

This will create a zolang.json file that will be used to specify build settings for your Zolang and setup the project's file structure.


### Example

#### The Config File

A typical ```zolang.json``` project file compiling to Swift, Kotlin and Python would look something like this:

```JSON
{
"buildSettings": [
{
"sourcePath": "./.zolang/src",
"stencilPath": "./.zolang/templates/swift",
"buildPath": "./.zolang/build/swift",
"fileExtension": "swift",
"separators": {
"CodeBlock": "\n"
},
"flags": [
"swift"
]
},
{
"sourcePath": "./.zolang/src",
"stencilPath": "./.zolang/templates/kotlin",
"buildPath": "./.zolang/build/kotlin",
"fileExtension": "kt",
"separators": {
"CodeBlock": "\n"
},
"flags": [
"kotlin"
]
},
{
"sourcePath": "./.zolang/src/",
"stencilPath": "./.zolang/templates/python2.7",
"buildPath": "./.zolang/build/python2.7",
"fileExtension": "py",
"separators": {
"CodeBlock": "\n"
},
"flags": [
"python2.7"
]
}
]
}
```

Notice the `./.zolang/templates/{LANGUAGE}` This is the location of the `.stencil` files that customize the actual code generation process. The Zolang organization has [a repo of supported languages](https://github.com/Zolang/ZolangTemplates). But `zolang init` only fetches the three (Swift, Kotlin and Python).

`./zolang/src` is where all the Zolang code is stored.

`flags` are compile time constants that can be used in ```only``` statements see [docs](#Docs)

> πŸ˜‡ P.S. It only took around an hour to add the templates needed to be able to compile Zolang to both Kotlin and Swift! So you shouldn't restrain yourself from using Zolang if your favorite language is not yet supported. Just add it and continue hacking.

#### Your First Model Description

We could create a file `./zolang/src/Person.zolang`

```zolang
describe Company {
name as text
revenue as number

employeeNames as list of text default []
}
```

#### Building

Just ...

```
zolang build
```

... and enjoy checking out the readable code generated to `./zolang/build/swift/Person.swift` and `./zolang/build/kotlin/Person.kt`

#### Hot Reloading

Zolang supports hot reloading or live compilation through the `watch` action

```
zolang watch
```

This action will observe changes to Zolang source files with paths specified in `zolang.json` and rebuild.

![Zolang hot-reloading](https://github.com/Zolang/Zolang/blob/master/Images/hot-reload-demo.gif "Zolang live compilation demo")


### Language Overview


#### Types

Zolang has five primitive types

- boolean
- text
- number
- list
- dictionary

##### boolean

Values are either ```true``` or ```false```

See section below on operators for further information

##### text

Defined within double quotes

```
"a piece of text"
```

You can format a piece of text using ```${...}```

```
"this is a string with an embedded variable: ${someVar}"
```

The limitation when it comes to ```text``` in Zolang is that the language doesn't care for characters that need to be escaped.

The text: ```"this is a text \n"``` would remain unchanged when compiling to other languages which might become a problem if `\n` is handled differently in the other languages the Zolang code is being compiled to. Thankfully languages seem to handle character escaping in a somewhat similar fassion so most of the time this does not make a difference.

##### number

Zolang currently only has one type to represent numbers.

Numbers work just as you would expect:

```zolang
let num1 as number be 0.12345

let num2 as number be 5
```

##### list

The same goes for lists. They represent ... you guessed it, lists of data; and are declared by using the ```list``` keyword followed by a ```of``` keyword and finally the type of the element you want to represent.

List literals are defined with a comma separated sequence of expressions wrapped inside enclosing brackets ```[...]```

```zolang
let myList as list of text be [ "1", "2", "3" ]
```

##### dictionary

Dictionaries might be a bit different to the key-value types you're used but fear not they're just as easy to understand.

In Zolang dictionaries only have one available Key type, `text`, so their usage becomes similar to lists:

```zolang
let myDict as dictionary of number be { "num1": 5, "num2": 7.5 }
```

This is to make sure all pure Zolang models are easily serializable to JSON so that later on templates in [ZolangTemplates](https://github.com/Zolang/ZolangTemplates) will be able to autogenerate serialization methods for all models.


#### Operators

##### Prefix Operators

There is only one supported prefix operator in Zolang

```not``` and ```!``` both meaning the same thing and are meant to be used as negation for boolean types

##### Infix Operators

Infix operators in Zolang:

- ```or```, ```||```: boolean or
- ```and```, ```&&```: boolean and
- ```<```: less-than
- ```>```: greater-than
- ```<=```: lesser-than-or-equal
- ```>=```: greater-than-or-equal
- ```equals```, ```==```: equality
- ```plus```, ```+```: addition
- ```minus```, ```-```: subtraction
- ```multiplied by```, ```times```, ```*```: multiplication
- ```divided by```, ```over```, ```/```: division
- ```modulus```, ```%```: modulus

> NOTE! Watch out for precedence. Zolang offloads precedence handling to the languages being compiled to. With types that are of number type this is seldom an issue but as Zolang doesn't currently support type checking, any operator can be used on any type, so beware.


#### Comments

Zolang currently only supports single line comments prefixed by `#`. Currently, comments are ignored in the build phase and can only be used to document Zolang code.

```zolang
# This is a comment
```


#### Describing a Model

```zolang
describe Person {
name as text
street as text
number as number
friendNames as list of text
}
```

Now like you can create a `Person` by calling:

```zolang
let john as Person be Person("John", "Wall Street", 15, [ "Alice", "Bob" ])
```

##### Access Control

It can be handy to be able to specify some ground rules as to what code can access what properties.

If we look at `Person` example from above we might want to limit access to his address to be only accessable from within the `Person`'s description.

This can be done by using the `private`Β access limitation specifier

Currently supported access limitation specifiers are
- `private`

If nothing is specified the property/function will be declared public

```zolang
private street as text
private number as number
```

##### Default Values

Properties can also have default values

```zolang
private street as text default "John"
```

##### Static

Zolang allows static declaration of properties/functions:

```zolang
static species as text default "Homo Sapiens"
```

This can then be accessed by calling:

```zolang
Person.species
```


#### Variable Declaration

```zolang
let person as Person be Person("John Doe", "John's Street", 8, [ "Todd" ])
```


#### Mutation

```zolang
make person.name be "Jane Doe"
```


#### Functions

Functions in Zolang can be declared in a model description, in `Person`, the model we described above we could define a function address which would combine street and number as so:

```zolang
describe Person {
name as text
street as text
number as number
friendNames as list of text

address return text from () {
return "${street} ${number}"
}
}
```

##### Invoking Functions

```zolang
person.speak("My address is ${person.address()}")
```


#### Arithmetic

Lets say we wanted to calculate something like `1 + 2 + (3 * 4) / 5`

In Zolang this would be written in various ways:

```zolang
1 + 2 (3 * 4) / 5
```

```zolang
1 plus 2 plus (3 times 4) over 5
```

```
1 plus 2 plus (3 times 4) divided by 5
```


#### Looping through Lists

```zolang
let i as number be 1

while (i < person.friendNames.count) {
make i be i plus 1
}
```


#### Metaprogramming

In Zolang there are two features designed for metaprogramming purposes, ```raw``` and ```only```

##### raw

```zolang
raw {'Any text here'}
```

This will tell the compiler to skip the code generation process for "Any text here" and forward it as is to the compiler's output

##### only
```only "", "",... { }```

Using `only` we can tell the compiler to ignore code for buildSettings not included in a comma separated list of flags (flags are specified in `./zolang.json` under `"flags"` in each buildSetting)

```zolang
only "python2.7", "swift" {
print("text")
}
```

##### Putting it all Together

Using these two features (`raw` & `only`) we could create a facade for logging to the console:

```zolang
describe Sys {
static log return from (txt as text) {
only "python2.7", "swift" {
raw {'print(txt)'}
}
only "kotlin" {
raw {'println(txt)'}
}
}
}

Sys.log("Hello World!")
```


## Roadmap / Upcoming Features

- Faster compilation
- Fetch [ZolangTemplates](https://github.com/Zolang/ZolangTemplates) from the Zolang CLI
- Update Zolang from the Zolang CLI
- Type checking
- For loop
- Function mutation


## Why Zolang?

Zolang doesn't try to be a general purpose programming language, it is limited in features and is yet to have a standard library, so why use Zolang instead of other programming languages?

... well, it's transpilable to multiple languages including Kotlin, Swift and Python and there are few limits to how many languages can be supported, to give you the idea of how soon your favorite language will be supported (if not already) adding support for all the three aforementioned languages took about an hour.

This means that Zolang is very good for implementing basic logic in your app with a single source of truth, generating code needed for virtually all platforms your app is running on.

### A User Story: The Story Behind Zolang

The idea for Zolang came from within a fast moving startup. It was moving fast in the sense that the tech stack was rapidly changing every now and then, the product had projects in 4 languages, Swift, TypeScript, JavaScript and Ruby. All of which had duplications in definitions of models.

So every time the tech stack changed drastically, changes had to be made in many of the (if not all four) implementations. So we wanted a language where we could write the model layer of our application with a single source of truth, generating code for all of our programming languages.


## Name

I'm a Star Wars fan and in the Star Wars world Zolan is the home planet of a species called clawdites, who are known for their ability to transform their appearance to look like virtually any other creature.

As the language aims to be transpilable to virtually any other programming language the clawdites came quickly to mind. Sadly the species doesn't have a catchy name, so I found myself falling back to their planet Zolan. And since this is a language and lang is often used as an abbreviation for language the "g" was soon to follow.

Remember this guy from "Attack of the Clones":

![Clawdite](https://github.com/Zolang/Zolang/blob/master/Images/clawdite.gif "The clawdite from Attack of the Clones")

That is a clawdite, my inspiration for the name and logo.


## License

MIT License

Copyright (c) 2018 Thorvaldur Runarsson

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.