How it works
Rune is written in Rust, and works by tokenizing your code with the logos lexer, then follows these steps:
- After tokenization, the tokens are run through token by token and parsed for each token, if a statement requires multiple tokens, such as with a function, the parser finds the necessary tokens based on index and then parses the whole statement.
- Then, before executing, the statement is logged to the stack trace to log in case of an error
- Then the statement is executed and the result is returned as a variable which is then added to the given collection using a Hashmap which stores all collections, and each collection contains a Vec of variables, and each variable contains a name and a value, which is stored as an enum that can be either a string, number, boolean, lambda function or array.
- Types are checked via a very simple type inference system which enforces static typing and infers the types of your variables with basic rules such as if the string starts and ends with quotes, it's a string.
- Then if an error is thrown, the entire stack trace is filtered for relevant references to the error and then printed up to the given amount provided by the --stack-length flag, or if it is not provided the default is 15 lines of the stack trace.
Performance
Rune is a decent speed for an interpreted language, here are some benchmarks against python:
| Operation | Rune | Python |
|---|---|---|
| Print "HELLO WORLD" 1000 times | ~1.36606ms | ~2.11407ms |
| Counter where the variable is freed after each increment(because that's how Rune does it) n=100 | ~1.26911ms | ~0.01374ms |
| Search a 100 element array for a value | ~0.01963ms | ~0.01299ms |