Minilux is a minimal language designed for simplicity and learning. It features:
- Variables with dynamic typing (integers, strings, arrays)
- Control flow (if/elseif/else, while loops)
- Functions (user-defined and built-in)
- Arrays with indexing and manipulation operations
- String operations including indexing and interpolation
- TCP sockets for network programming
- Shell integration for executing system commands
To build minilux from source, you need the Rust toolchain (cargo + rustc)
Install on Debian/Ubuntu/GoldenDog:
sudo apt install cargo
Fedora:
sudo dnf install rust cargo
macOS (via homebrew)
brew install rust # this installs both rustc and cargo
Other systems:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
make
make install
This installs minilux to /usr/bin, allowing you to run scripts directly with a shebang.
mac users: to build on macOS, edit the Makefile and change the path to /usr/local/bin
To uninstall run ```make uninstall``
remove the target/ dir completely (rm -rf target/), and then:
make uninstall; make clean; make
./minilux examples/test.miOr make the script executable:
chmod +x examples/test.mi
./examples/test.miVariables start with $ and can hold integers, strings, or arrays:
$name = "Alexia"
$age = 42
$result = 1 + 2
$list = [1, 2, 3]
Important: Compound boolean conditions require double parentheses:
if (($age >= 18) AND ($name == "Alexia")) {
printf("Adult named Alexia\n")
}
elseif ($age >= 13) {
printf("Teenager\n")
}
else {
printf("Child\n")
}
Simple conditions work with single parentheses:
if ($age >= 18) {
printf("Adult\n")
}
$i = 1
while ($i <= 5) {
printf("Count: ", $i, "\n")
inc $i + 1
}
==equal!=not equal>greater than<less than>=greater than or equal<=less than or equal
ANDor&&logical andORor||logical or
Note: When using AND/OR operators in conditions, use double parentheses:
if (($x == 1) AND ($y == 2)) {
printf("Both conditions met\n")
}
if (($a != 0) OR ($b != 0)) {
printf("At least one is non-zero\n")
}
+addition-subtraction*multiplication/division%modulo
Expressions support parentheses:
$result = (10 + 5) * 2
$calc = 1 + (4 / 2)
Create and manipulate arrays:
$arr = [1, 2, 3]
printf("Element 0: ", $arr[0], "\n")
printf("Length: ", len($arr), "\n")
push $arr, 4
pop $arr
shift $arr
unshift $arr, 0
String indexing also works:
$text = "Hello"
printf("First char: ", $text[0], "\n") # prints "H"
printf("Length: ", len($text), "\n") # prints "5"
Print text and variables by concatenating all arguments:
# Concatenate strings and variables
printf("Hello, ", $name, "!\n")
print("I am ", $age, " years old\n")
# Print numbers
printf("Number: ", 42, "\n")
# Mix text and variables
printf($name, " is ", $age, " years old\n")
# Single argument
printf("Hello world\n")
printf($name)
print is an alias of printf; both names behave identically and automatically append a trailing newline when one is missing.
Escape sequences:
\nnewline\ttab
Note: If the output doesn't end with \n, one is automatically added.
Read a line from standard input (without the trailing newline) and store it in a variable:
printf("What is your name?")
read($name)
printf("Hello ", $name, "!)
Get the length of strings or arrays:
$text = "Hello"
printf("Length: ", len($text), "\n") # 5
$arr = [1, 2, 3]
printf("Array length: ", len($arr), "\n") # 3
Convert strings (or existing integers) into numeric values for arithmetic: IMPORTANT: parser fails return 0 (e.g: giving a non-numeric value for example number(hello))
read($input)
$value = number($input)
printf("Twice is ", $value * 2, "\n")
Normalize string casing in expressions:
$answer = "YeS"
if (lower($answer) == "yes") {
printf("Confirmed\n")
}
printf("Shouting: ", upper("minilux"), "\n")
Execute system shell commands and capture output:
$user = shell("whoami")
printf("Current user: ", $user, "\n")
# Commands with pipes
$count = shell("ls -l | wc -l")
printf("File count: ", $count, "\n")
# Date commands
$date = shell("date +%Y-%m-%d")
printf("Today: ", $date, "\n")
Note: The trailing newline is automatically removed from command output.
Increment or decrement variables:
$counter = 0
inc $counter + 1 # counter is now 1
inc $counter + 5 # counter is now 6
dec $counter - 2 # counter is now 4
push $array, value- Add element to endpop $array- Remove element from endshift $array- Remove element from beginningunshift $array, value- Add element to beginning
$list = [1, 2, 3]
push $list, 4 # [1, 2, 3, 4]
pop $list # [1, 2, 3]
shift $list # [2, 3]
unshift $list, 0 # [0, 2, 3]
Minilux supports TCP socket programming:
sockopen("name", "host", port)- Open a TCP connectionsockwrite("name", "data")- Send data to socketsockread("name", $var)- Read data into variablesockclose("name")- Close the socket
Example HTTP request:
sockopen("web", "example.com", 80)
sockwrite("web", "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
sockread("web", $response)
printf("Response: $response\n")
sockclose("web")
Include and execute other minilux files:
include "lib.mi"
Define reusable code blocks with func:
func greet {
printf("Hello from function!\n")
}
func show_name {
printf("My name is $name\n")
}
greet
show_name
Lines starting with # are comments (primarily for shebangs).
Minilux scripts use the .mi extension.
Make scripts executable with a shebang:
#!/usr/bin/minilux
$name = "World"
printf("Hello, $name!\n")
Then run directly:
chmod +x script.mi
./script.miSee the examples/ directory for sample programs:
test.mi- Basic language featuresarray_test_1.mi- Array operations and string indexingarray_test_2.mi- Array modificationhttp_test.mi- TCP socket usage
minilux/
├── src/
│ ├── main.rs # Entry point and CLI
│ ├── value.rs # Value type system
│ ├── lexer.rs # Tokenization
│ ├── parser.rs # AST generation
│ ├── interpreter.rs # Execution engine
│ └── runtime.rs # Runtime state management
├── examples/ # Example scripts
├── Cargo.toml # Rust dependencies
├── Makefile # Build automation
└── README.md # This file
make— Build the release binarymake install— Install to /usr/bin (requires sudo)make uninstall— Remove from /usr/binmake clean— Remove build artifacts
Requirements:
- Rust 1.85.0 or later
- Cargo (comes with Rust)
# Build debug version
cargo build
# Build optimized release version
cargo build --release
# Run tests
./target/release/minilux examples/test.miThis implementation was rewritten from C to Rust to provide:
- Memory safety - No segfaults or buffer overflows
- Better error handling - Proper error propagation
- Modern tooling - Cargo for builds and dependencies
- Maintainability - Cleaner, more organized code structure
- Type safety - Catch more bugs at compile time
Alexia Michelle
✉️ alexia@minilux.org
This project is licensed under the Mozilla Public License 2.0. See the LICENSE file for details.
By contributing to minilux, you agree to our Contributing Guidelines and the Future Relicensing Notice contained therein.
This interpreter is intentionally small and experimental — a great starting point for learning language design and implementation.
