How it works
Rune is written in Rust, and works by tokenizing your code with the logos lexer, then follows these steps: - After tokenization, a garbage collector system is run to identify unused variables and remove them before parsing - Next, 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 simple and robust 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.127558ms | ~2.11407ms |
| Calculate first 25 fibonacci numbers | ~0.075337ms | ~7.672817ms |
| Calculate pi to 1000 iterations with Leibniz series | ~4.201662ms | ~0.411562ms |
| Sort the same 100 number list | ~0.059186ms | ~0.1160909ms |