Scripting language implemented with Rust
Go to file
2017-08-25 23:48:38 +00:00
README.md Update README.md 2017-08-25 23:48:38 +00:00

Omega

What?

Omega is a language intended for scripting purposes. Omega is reads .omega files which contain Omega-code (specified below), which will then be parsed into bytecode, which can be run instantly, or later through the interpreter.

Why?

The original version of Omega was written in TypeScript for a NodeJS server for a dungeons and dragons system client. The new server is being written in Rust, so the language must be re-written. To make the process easier, here is the specifications (and technically the documentation) for the re-visited version of the language. To the same repository I will be creating the actual Rust implementation of this language too.

The original version of Omega can be viewed here

Who?

Omega is created by Teascade, original version being written with TypeScript in 2016, and new specification and Rust implementation written in 2017.

License?

Currently Omega has no license, since it is only a specification, but most likely it will be licensed under MIT later.

The Omega specification is simply CC-BY-SA:

Creative Commons License

Table of Contents

Table of contents for the Omega spec

Examples

Before any of the following examples, a print-function has been defined in the global scope. The print-function takes in a String-type as a parameter.

Example Hello World

print("Hello World!");

Example loop

let max = 15;
for (let i = 0; i < max; i++) {
  print("i: " + i);
}

General Syntax

The general syntax of Omega is fairly similar to that of TypeScript or Rust. The syntax is a mix of keywords and expressions displayed such as in the examples.

Expressions

Expressions are a set of values, function calls and operators that Omega interprets and returns a new value out of.

For example 2 + 3 is an expression combined by a +-operator which will result 5

Function calls

Function calls are also very similar to other languages. If there esists a function called function_one, it can be called with function_one();. If there exists a function called function_two which requires two i32's as arguments, it can be called as function_two(5, 2); where 5 and 2 are example integer values.

  • Function calls must have parenthesises in the end of them to signify the call, and after the parenthesis there must be a semicolon ;.
  • Any possible arguments must be given between the parenthesis separated by commas,.

Operators

Operators are a number of individual and combined symbols which together form meanings which are interpreted in a special way.

  • +
    • Plus-operator. Combines the two values surrounding it.
    • Examples:
      • 2 + 3 returns 5
      • "Hello" + "!" returns "Hello!"
  • -
    • Minus-operator. Removes the second value from the first.
    • Examples:
      • 2 - 3 returns -1
  • *
    • Multiplication-operator. Multiplies the surrounding values.
    • Examples:
      • 2 * 3 returns 6
  • /
    • Division-operator. Divides the first value with the second.
    • Examples:
      • 6 / 3 returns 2
      • 2 / 3 returns 0.666..
  • %
    • Modulo-operator. Retrns the remainder from the division of the first value by the second.
    • Examples:
      • 2 % 3 returns 2
      • 6 % 3 returns 0
      • 10 % 3 returns 1
  • ++
    • Addition-operator. Special operator, which adds one to the value before it. Examples:
      • 1++ returns 2
      • 2++ returns 3
  • Some operators are listed under Conditions

Scopes

Scopes are areas of code surrounded by brackets {}. E.g.

let variable = "text";
{
  let this_is_scoped = "scoped_text";
  this_is_scoped = variable + "!";
}
variable = this_is_scoped; // Exception! Cannot access inner-scope.

As is visible in the example, variables defined in the scope are no longer accessible outside the scope. Scopes exist in their individual "environments", where they can access the variables in their upper scopes, but not inner scopes.

Conditions

Conditions are a special kind of expression, which will return a boolean value.

Conditions may be simply true or false, or tests like var, where var is a boolean-type variable, or name == "test", where name is a string-type variable.

Conditions can also be set as values for variables, since they explicitly return a boolean value.

Operators for conditions are

  • == for equals.
  • != for not equals.
  • || for or.
  • && for and.
  • ^ for xor.

Any of these can be mixed with any of them, and can be wrapped in parenthesis to priorisize which must be tested first. Examples:

let first = true;
let second = first == true;
let third = second && first;
let fourth = "otus" == "test" || (first ^ second);

Values

There are a number of values you can assign to your variables, as of Omega 1.0, only primitive values are possible. Such types are:

  • string, a basic piece of text, defined as followes: "String here".
  • char, contains a single character, defined as follows: 'c'
  • i8 (or usually short), a basic 8-bit integer value, such as 3 or 11.
  • i32 (or usually int), a basic 32-bit integer value, such as 3 or 11.
  • i64 (or usually long), a basic 64-bit integer value, such as 3 or 11.
  • f32 (or usually float), a basic 32-bit float value, such as 1.5 or 6.32.
  • f64 (or usually double), a basic 64-bit float value, such as 1.5 or 6.32.
  • boolean, contains value of true or false. This also includes conditions.

Keywords

The following keywords are specified to execute an action.

  • let initializes a new variable.
  • def defines a new function.
  • while initializes a scope which will be ran while a condition applies, which is specified after the while.
  • for initializes a scope which will be ran a number of times specified after the for.
  • All operators are also somewhat considered as keywords.

let

Initializes a new variable, as such:

let uninitialized: string; // Initializes this variable as string, but does not give it a value.
let five = 5;              // Sets five to 5
let var = "text";          // Sets var to "text"
let five = 6;              // Causes an exception, cannot re-define five
five = 3;                  // (without let-keyword) Re-sets five to 3
  • Initialization of new variable must contain let, but re-definition of an existing variable, cannot start with let.
  • The name of the variable being defined must follow the let after whitespace.
  • After the name of the variable, there may be a definition of the type of the variable, but it is not necassary. When re-defining a value of a variable, there cannot be a re-definition of the type.
    • If there is no type-definition, an initializing value must be set.
    • type-definition's form is as follows: : T, and it cannot be preceded by whitespace. between the colon and the T there may be whitespace.
  • After whitespace, there may be (or must be, if no type-definition is given), an equals=-sign, after which there must be more whitespace, after which the value of the variable is given.
  • After the value of the variable, the let-expression must end in a semicolon ;.

def

Defines a new function or method as follows:

def first_function() {
  // Code
}

def second_function(param1: string) {
  // Code
}

def third_function(param1: i32, param2: string) {
  // Code
}
  • The initialization of the function/method must begin with def.
  • After def there must be a number of whitespace, after which the name of the defined function must follow.
  • Immediately after the name of the function, there must be an opening parenthesis (.
  • After the opening bracket there may be parameters listed.
    • Format of the parameters follows the let format, without the let-keyword.
    • There must also be a type-definition.
    • There cannot be any default values. (no equals=-sign)
    • The parameters are divided by a comma,, after which there may be any number of whitespace.
  • After the list of parameters there must be a closing bracket ).
  • Between the parenthesis and the parameter-lists, there may be any number of whitespace.
  • After the parenthesis and any number of whitespace, there must be a scope definition.

while

Defines a loop which will be as long as the condition defined after it is met.

while (true) {
  // Runs infinitely.
}

while (false) {
  // Never enters this loop.
}

while (true == false) {
  // Also never enters this loop.
}
  • To specify a while, the line must begin with a while.
  • After the while, there can be a number of whitespace, after which there must be parenthesis, within which (like parameters are in def), there must be a boolean value or otherwise known as a condition.
  • After the parenthesis there must be a scope definition.

for

Defines a loop very similar to while, but which parameters inside the parenthesis consists of three parts separated by semicolons;.

for (let i = 0; i < 10; i++) {
  // Loop through 0 to 10
}
  • The first part (let i = 0 in this example) is the beginning-expression. It can be any expression, and it will be executed as the loop begins weather or not the scope inside the loop will be accessed.
  • The second part (i < 10 in this example) is the condition defining weather the loop-scope will be accessed or not.
  • The third part (i++ in this example) is the step-expression, which will be executed after each execution of the loop-scope.
  • Otherwise for is identical to while