- WindLang, A simple programming language built with golang π
- What is wind?
- Playground
- Cool but why?
- Why Golang, not Rust?
- How to use it?
- So what can it do?
- Hello world?
- Variables
- Data types
- Arrays
- Array.push(element) -> any[]
- Array.pop() -> any
- Array.removeAt(index) -> any
- Array.len() -> int
- Array.join(separator) -> string
- Array.map(function) -> any[]
- Array.filter(function) -> any[]
- Array.reduce(fn(accumulator, element), initialValue) -> any
- Array.contains(function) -> boolean
- Array.count(function) -> int
- Array.clone() -> any[]
- Strings
- String.len(separator) -> int
- String.charAt(index) -> string
- String.contains(substr) -> boolean
- String.containsAny(substr) -> boolean
- String.count(substr) -> string
- String.replace(old, new) -> string
- String.replaceAll(old, new) -> string
- String.replaceN(old, new, n) -> string
- String.changeAt(index, new) -> string
- String.indexOf(substr) -> int
- String.lastIndexOf(substr) -> int
- String.split(separator) -> string[]
- String.trim() -> string
- String.toLowerCase() -> string
- String.toUpperCase() -> string
- Functions
- Closures
- If expressions
- Include statement
- For loops
- While loops
- HashMaps
- Todos
Wind is an interpreted language written in golang.
The easiest way to play with WindLang is to use the playground
I'm working on this as a side project and it's the 5th attempt at writing my own programming language, And it got me my first job too! it's awesome π
I already tried to build this with Rust, but I battled a lot with the Rust compiler and felt like golang is a better middle ground I got so much faster with golang, and it was surprising that the golang implementation was actually faster! Not because golang is faster than rust, it's my lack of knowledge, and the way I code is not "Rusty"
Head up to the releases page and download Wind for your operating system
And execute windlang executable
WindLang, A simple programming language written in golang
Usage:
windlang [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
run Run a Wind script
Flags:
-h, --help help for windlang
-t, --toggle Help message for toggle
Use "windlang [command] --help" for more information about a command.
This is the Wind cli you can use the run command to run a Wind script file Install the vscode extension here!
Let me demonstrate the features implemented as of now
println("Hello world");
Yes, Wind can print Hello world, Surprising huh?
let x = 1;
println(x); // 1
x = "Hello world";
println(x); // Hello World
You can declare variables in Wind with the let
keyword, Variables in wind are dynamically typed and you can reassign them to any type.
1 // int
3.14 // float
true, false // boolean
nil // null
"Hello World" // String
[1, "2", true] // Arrays
{
"name": "Youssef",
"age": 18
} // HashMaps
let arr = [1, "2", true];
println(arr[0]); // 1
println(arr[1]); // 2
println(arr[2]); // true
arr.push("3") // [1, "2", true, "3"]
println(arr[3]); // 3
arr.pop() // [1, "2", true]
Arrays in Wind can take any type of data, and can be of any size
You can append to an array by using the append
function
You can remove an element by index using the remove
function.
let x = [1, 2, 3];
x.push(4) // [1, 2, 3, 4]
Array push function adds an element to the end of the array
let x = [1, 2, 3, 4];
x.push(4); // [1, 2, 3, 4]
let y = x.pop(); // [1, 2, 3]
println(y); // 4
Array pop function removes the last element of the array and returns it
let x = [1, 2, 3, 4];
x.push(4); // [1, 2, 3, 4]
let y = x.removeAt(3); // [1, 2, 3]
println(y); // 4
Array removeAt function removes an element at the index of the array and returns it
let x = [1, "hi", true];
println(x.len()); // 3
Array len function returns the length of the array
let x = [1, "hi", 3, 4];
println(x.join("-")); // 1-hi-3-4
Array join function returns a string with all the elements of the array separated by the separator
let x = [1, 2, 3];
println(x.map(fn(x) {x * 2})); // [2, 4, 6]
Array map function applies the function to each element of the array and returns a new array with the results
let x = [1, 2, 3, 4];
let even = x.filter(fn(x) { x % 2 == 0});
println(even); // [2, 4]]
Array filter function applies the function to each element of the array and if the function returns true, the element is added to the new array
let x = [1, 2, 3, 4, 5];
let sum = x.reduce(fn(acc, x) { acc + x}, 0);
println(sum); // 15
Array reduce function applies the function to each element of the array and returns a single value
let arr = [1, 3, 5];
println(arr.contains(fn(x) { x % 2 == 0})); // false
arr = [1, 2, 3, 4, 5];
println(arr.contains(fn(x) { x % 2 == 0})); // true
Array contains function applies the function to each element of the array and returns true if the function returns true for any element
let arr = [1, 3, 5];
println(arr.count(fn(x) { x % 2 == 0})); // 0
arr = [1, 2, 3, 4, 5];
println(arr.count(fn(x) { x % 2 == 0})); // 2
Array count function applies the function to each element of the array and returns the number of times the function returns true
let x = [1, 2, 3];
let notCloned = x;
let cloned = x.clone();
x[0] = "changed";
println(notCloned[0]); // Changed
println(cloned[0]); // 1
Array clone function returns a copy of the array
Strings in Wind start and end with a double quote "
and can contain any character and can be multi-line
let x = "Hello";
println(x.len()); // 5
String len function returns the length of the string
let name = "youssef";
println(name.charAt(0)); // y
String charAt function returns the character at the specified index
let name = "youssef";
println(name.contains("ss")); // true
String contains function returns true if the string contains the exact substring
let vowels = "aeiou";
let name = "youssef";
println(name.containsAny(vowels)); // true
String contains function returns true if the string contains any character of the substring
let name = "youssef";
println(name.count("s")); // 2
String count function returns the number of times the substring appears in the string
let name = "John Doe";
println(name.replace("o", "x")); // Jxhn Doe
String replace function returns a new string after replacing one old substring with a new substring
let name = "John Doe";
println(name.replaceAll("o", "x")); // Jxhn Dxe
String replace function returns a new string after replacing all old substring with a new substring
let name = "Youssef";
println(name.replaceN("s", "x", 1)); // Youxsef
println(name.replaceN("s", "x", 2)); // Youxxef
String replace function returns a new string after replacing n of old substring with a new substring
let name = "Ahmed";
println(name.changeAt(0, "a")); // ahmed
String changeAt function returns a new string after changing the character at the specified index
let name = "John Doe";
println(name.indexOf("o")); // 1
String indexOf function returns the index of the first occurrence of the substring
let name = "John Doe";
println(name.lastIndexOf("o")); // 6
String indexOf function returns the index of the last occurrence of the substring
let name = "Youssef Ahmed";
let names = name.split(" "); // ["Youssef", "Ahmed"]
let firstName = names[0];
let lastName = names[1];
println("First name is: " + firstName); // First name is: Youssef
println("Last name is: " + lastName); // Last name is: Ahmed
String join function returns an array of strings by splitting the string by the separator
let name = " John Doe ";
println(name.trim()); // "John Doe"
String trim function removes whitespace from the start/end of the string and returns a new string
let name = "JoHn dOe";
println(name.toLowerCase()); // john doe
String toLowerCase function returns a new string with all the characters in lower case
let name = "JoHn dOe";
println(name.toUpperCase()); // JOHN DOE
String toLowerCase function returns a new string with all the characters in upper case
let add = fn(x, y) { x + y; };
// This is the same as
let add = fn(x, y) {
return x + y;
};
println(add(1, 2)); // 3
Yes, this looks like Rust functions. The last expression in a function is implicitly returned
let addConstructor = fn(x) {
fn(y) {
x + y;
};
};
// This is the same as
let addConstructor = fn(x) {
return fn(y) {
return x + y;
};
};
let addTwo = addConstructor(2); // This will return a function
println(addTwo(3)); // 5
This is one of the coolest things implemented in Wind. As I said functions in Wind are expressions, so you can return a function or pass a function to another function.
let welcome = fn(name, greeter) {
greeter() + " " + name
};
let greeter = fn() { "Hello π"};
println(welcome("Wind π", greeter)); // Hello π Wind π
// Use if as an expression
let grade = 85;
let msg = if (grade > 50) { "You passed" } else { "You didn't pass" };
println(msg); // You passed
// Or use if as a statement
if (grade > 50) {
println("You passed");
} else {
println("You didn't pass");
}
As you can see here we can use it as an expression or as a statement
Note that after any expression the semicolon is optional. We can type "You passed";
or "You passed"
and it will implicitly return it
// test.wind
let msg = "Hello π";
let greeter = fn() {
println(msg);
};
// main.wind
include "./test.wind";
greeter(); // Hello π
// You can also alias includes
include "./test.wind" as test;
test.greeter(); // Hello π
Include statements allow you to include other Wind scripts, It initializes them once and can be used by multiple files at the same time while preserving state.
let names = ["Youssef", "Ahmed", "Soren", "Morten", "Mads", "Jakob"];
for (let i = 0; i < len(names); i++) {
println("Hello " + names[i]);
}
// Hello Youssef
// Hello Ahmed
// Hello Soren
// Hello Morten
// Hello Mads
// Hello Jakob
let x = 0;
while (x < 5) {
println(x);
x++;
}
// 0
// 1
// 2
// 3
// 4
let person = {
"name": "Youssef",
"age": 18,
"incrementAge": fn() {
person.age++;
}
};
println(person["name"]); // Youssef
println(person.age); // 18
person.incrementAge();
println(person.age); // 19
Hashmaps are like js object and can store key value pairs, Keys can be integers, strings and booleans. Values can be any type.
-
Named include statements -
HashMaps (Javascript objects -
A bytecode interpreter maybe