oko-lang (or simply oko) is an interpreted, non-esoteric programming language the official implementation of which is powered by the Deno JS runtime. Features most of the things that you can find in other languages - variables, complex data structures, functions, program flow control, loops, rich standart library (built-ins) and more.
At the moment, oko-lang is in its early stage of development. Expect ground-breaking changes, no backward compatability, significant performance and development experience improvements and much more. If you would like to contribute to the language by any means, we have a discord server. There you can contact me - the main developer - and other people who are willing to help us build oko.
If you happen to be using Visual Studio Code as your primary code editor / IDE, there is an official extension for the oko programming language. Some of the features include:
- Syntax Highlighting
- Code Snippets
- Keyword Snippets
- File icon(s)
There are 2 main ways to install the oko programming language.
1οΈβ£ First Method: Head into the Releases/ page of this repository. Afterwards, download the version you are interested in for your respective OS and architecture. This is by far the easiest way to get the oko-lang executable.
2οΈβ£ Second Method: For this method, you need to have the Deno JS runtime installed on your machine. Download the source code of oko, and then use Deno to compile oko by using a command similar to this one: deno compile --allow-all oko.js
Once you got the oko-lang executable, you can easily execute .oko
files:
oko <Filename>.<FileExtension>
If you would like to see some information regarding oko-lang's license, use oko license
.
The syntax of oko is dead simple. Every statement (besides the ones that end in { blocks }
) should have a trailing semicolon ;
. Example:
io::println("Hello, World!");
To define variables, you use the :=
assignment operator. There also are other ones, like =
, +=
, -=
, *=
and /=
. The difference between :=
and =
is that the =
operator can by definition only mutate an existing variable - it can't be used to change a variable's type or to set a value to a variable that hasn't been declared and initialized yet.
var := 13;
var += 13;
var -= 13;
var *= 13;
var /= 13;
var = 13;
Just so you know, there are only single-line comments in oko, which use the following syntax:
// this is a comment
Here is an example regarding variables that will throw an error:
msg := "Hello, World!";
msg = -0.13 // can't change the variable's type via `=` from String to Number
Now let's get to operators. Here's a complete list of them (this doesn't include the assignment ones): +
, -
, *
, /
, ^
, %
, >
, <
, ==
, >=
, <=
, &&
, ||
. All of the operators listed were binary (infix). The latest version of oko features only one unary (prefix) operator: !
. All of these work as expected and work only with certain data types. Usually, when Nil
is either on the left or the right side of the expression the result is also Nil
- but there are exceptions to that rule.
Before we continue, you must know that the only 4 data types in oko are: String
, Number
, Array
and Nil
. This doesn't mean the language isn't capable though.
You can easily manipulate program flow via if
, elif
(else if
) and else
statements. As you already know there are no booleans, so numbers are usually used instead of them. An empty array []
, zero 0
, an empty string ""
and nil are all falsy - others are truthful. Here is a code example that will output Omega
:
import io;
import tu;
if ("") {
io::println("Steak");
} elif ([]) {
io::println("Trophy");
} elif ( tu::getNil() ) {
io::println("Cat");
} elif (1) {
io::println("Omega");
} else {
io::println("Princess");
}
At the moment, oko features 2 types of loops: while
and for
(which is a forEach
). Here's an example for you:
import io;
j := 1;
while (j <= 5) {
io::println(j);
j += 1;
}
items := ["Apple", "Banana", "Pear"];
for (el) (items) {
io::println(el);
}
The output will be as following:
1
2
3
4
5
Apple
Banana
Pear
As you may have already noticed, we import
a lot of things to get things done. The import
keyword allows us to import built-in modules of oko. Here is a list of all modules and the respective functions they expose:
-
prog
(Program Control)exit(code)
: Exits the program with the specified numeric exit codethrow(msg)
: Throws an error with the given string message
-
time
(Time Utilities)now()
: Returns the current timestamp in milliseconds since the Unix epochsleep(ms)
: Stops the program execution for a certain amount of milliseconds.
-
tu
(Type Utilities)getNil()
: Returnsnil
(no value)toNumber(value)
: Converts a value to a number, if a string can not be converted to a number returns Nil, errors if value is an arraytoString(value)
: Converts a value to its string representationtypeOf(value)
: Returns the type of the given value as a string
-
io
(Input/Output)input()
: Prompts the user for input, returns a string or nil if emptyπ΄ Does not work at the moment because of the issues caused by Deno and the inability to easily flush the standart output.print(...args)
: Prints values without newline, joined by spaceprintln(...args)
: Prints values with newline, joined by spacereadTextFile(path)
: Reads the contents of a text file at the given path. Returns the contents on success and Nil on failure.writeTextFile(path, content)
: Writes the content string to a file at the given path, returns 1 on success and Nil on failure.
-
math
(Mathematical Functions)sqrt(num)
: Returns the square root of a number or nil if invalidabs(num)
: Returns the absolute value of a numberround(num)
: Returns the floor of a number (rounded down)ceil(num)
: Returns the ceiling of a number (rounded up)floor(num)
: Returns the floor of a number (rounded down)sin(num)
: Returns the sine of a number (radians)cos(num)
: Returns the cosine of a number (radians)tan(num)
: Returns the tangent of a number (radians)log(num, base)
: Returns the logarithm of a number with specified baserandom()
: Returns a random floating-point number between 0 and 1
-
stru
(String Utilities)len(str)
: Returns the length of a stringat(str, index)
: Returns the character at the given index of a stringsub(str, start, end)
: Returns a substring from start to end indicessplit(str, delim)
: Splits a string by the delimiter into an array of stringslower(str)
: Converts a string to lowercaseupper(str)
: Converts a string to uppercasetrim(str)
: Trims whitespace from both ends of a stringreplace(str, find, replace)
: Replaces all occurrences offind
in the string withreplace
-
arru
(Array Utilities)len(arr)
: Returns the length of an arrayat(arr, index)
: Returns the element at the given index in an arraypush(arr, val)
: Adds a value to the end of an arrayremove(arr, index)
: Removes and returns the element at the given index in an arrayjoin(arr, separator)
: Joins array elements into a string separated by the given separator, replacing nil elements with "Nil"
To use any of the described functions, you need to firstly import
the module you want to use, f.e.:
import io;
And then call any function from that specific module via the mod access operator mod::func
:
io::println("msg");
It's that simple.
At last, here's how you can create your own functions. You need to use the fun
keyword to do so. Here are some code examples:
import io;
fun sum(a, b) {
return a + b;
}
fun thisReturnsNil(msg) {
io::println(msg);
}
If a function doesn't feature a return
statement, it returns Nil
- which by the way doesn't have its own specific keyword. The easiest way to get Nil is by using tu::getNil()
module method.
You also are allowed to nest function definitions:
import io;
fun outer(a, b) {
fun inner(c) {
return a + b + c;
}
return inner(5);
}
io::println(outer(2, 3));
This outputs 10
.
The name oko-lang
(or rather oko
) was chosen for no specific reason by me, tixonochek. Whether it was the best possible choice at the time or not, the name oko
allowed me to create a fitting logotype and slogan for the language.
oko-lang uses the GNU General Public License version 3. For more information, check the LICENSE
file of this repository or use the oko license
command (the first method is preffered).