VM_Lang

A basic interpreted programming language written in Rust as a fun exercise.

Basic structure

A program written in the language is made up of a number of functions, one of which must be named main, take no arguments and have return type void.

Functions

Has a name, a list of arguments and an optional return type followed by a block statement.

Ex: fn some_func(a: int, b: [string]): boolean { // Statements return true }

If a function has a return type it MUST use a return statement on every path through the function, otherwise a return is optional.

Comments

Any text after // in a line is ignored (unless the // are within a string literal).

Statements

Let

Declares a variable, type is inferred.

Ex: let a = 0;

While

A loop that continues as long as the provided expression holds true.

Ex: while true { // Statements }

For

A for-each loop going iterating through a list.

Ex: let some_list = [1, 4, 9]; for (a in some_list) { // Statements }

If

A branching statement, runs the block if the expression holds true.

Ex: if true { // Statements }

If else

A branching statement, runs the first block if the expression holds true, otherwise runs the else block.

Ex: let i = 4; if i < 2 { // Statements } else { // Statements }

Return type

Returns from the current function with the provided expression, the type of the expression must be the same as the return type of the function.

Ex: return 54;

Return void

Returns from the current function when the function has return type void.

Ex: return;

Expressions

An expression ended with a semi-colon ; is also a statement.

Ex: i++;

Blocks

Wraps a list of statements creating a new scope.

Ex: { // Statements }

Expressions

There are a number of expressions in the language, in order of priority they are:

Assignment

Reassigns a previously declared variable.

Ex: a = 2;

Comparison

Compares two expressions of the same type returning a boolean.

Comparisons supporting only boolean expressions: - || | 'or' is true if either of the expressions are true. - && | 'and' is true if both of the expressions are true.

Comparisons supporting all(?) types: - == | equals is true if the expressions are the same. - != | not equals is true if the expressions are no the same. - <= | Less than or equal to is true if the first expression is less than or equal to the second expression. - >= | Greater than or equal to is true if the first expression is greater than or equal to the second expression. - < | Less than is true if the first expression is strictly less than the second expression. - > | Greater than is true if the first expression is strictly greater than the second expression.

Ex: 2 < 4

Arithmetic operations

Performs an arithmetic operation between two expressions of type int.

The currently suppported arithmetic operations are: - + | plus - - | minus - * | times - / | division

Ex: 2 + 4

Unary operations

Operations on singular expressions.

The currently supported unary operations are: - ! | not - ++ | Increases the value by 1, depending on if put before or after the expression this will be done before or after the value is read. - -- | Decreases the value by 1, depending on if put before or after the expression this will be done before or after the value is read.

Ex: i++;

Function calls

Calls a function.

Ex: some_func(42, "this function has two args");

List indexing

Retrieves a value from a list by its index.

Ex: let some_list = [1, 5, 9]; some_list[1]; // Returns 5

Literals

A literal of any of the available types (except void).

Ex: 54

Parenthesised expression

Any expression wrapped in parenthesis.

Ex: (1 + 2)

Types

There are currently four types available in the language: - int, ex: -54 - bool, ex: true - string, ex: "Hello! This is a string" - lists, declared as [TYPE] where TYPE can be any of the above types, ex: [0, 1, 99, 200] - void, never directly used but is used when no other type has been declared for e.g. functions that have no return type.

Builtin functions

There are a few built-in functions available for specific tasks.

print_number

Prints the number to standard out.

Args: - number: int | The number to print.

Returns: `Void

print_string

Prints the string to standard out.

Args: - text: string | The string to print.

Returns: Void

print_bool

Prints the boolean to standard out.

Args: - val: bool | The boolean to print.

Returns: Void

read_number

Reads a number from standard in.

Args: None

Returns: - number: int | The number read.

read_string

Reads a string from standard in.

Args: None

Returns: - val: string | The string read.

read_bool

Reads a boolean from standard in.

Args: None

Returns: - val: bool | The boolean read.

read_file

Given a path, reads a file to a string.

Args: - file_path: string | The filepath relative to the current directory.

Returns: - file_content: string | The content of the file.

split_string

Given a string and a 'splitter', splits the string on each occurance of the 'splitter', returning a list of the parts.

Args: - text: string | The text to be split. - splitter: string | The text to split on.

Returns: - parts: [string] | A list containing every part of text split on each occurance of the splitter.

parse_int

Parses a string to a number.

Args: - text: string | The text to parse.

Returns: - num: int | The parsed text.