Welcome to the documentation for the Sahl programming language. Below, you'll find detailed information about the language features and syntax.
|
|
|
|
Let's start with the traditional "Hello World" program:
fun main() {
print("Hello World! \n");
}This basic program defines a main function and prints the classic greeting.
Functions are fundamental in Sahl. Here's an example of a function adding two integers:
fun add(a: int, b: int) -> int {
return a + b;
}If the return type is unspecified, it defaults to void.
Variables store and manipulate data. Check this example:
fun main() {
let a = 10;
let b = 20;
let c = a + b;
print(c, "\n");
}Variable types are inferred from assigned values.
Constants are declared with the const keyword outside of functions:
const PI = 3.14;
const AREA = PI * 10 * 10;
fun main() {
print("Area of circle of radius 10 is ", AREA, "\n");
}Sahl supports various types, including basic ones like int, double, bool, string, and char. It also includes more complex types like arrays, tuples, maps, and channels.
let a = [1, 2, 3];let myTuple = (10, "Hello",); // trailing comma is nessesarylet myMap = map<int, string>;let myChannel = chan<int>;type Person = PersonS(string) | PersonI(int);Essential statements include if, while, for, break, continue, and return. Let's explore a few:
if a > 0 {
a = a + 1;
}while a > 0 {
a = a - 1;
}for i in 0..10 {
print(i, "\n");
}Works for types with constructors and also as a switch statement.
type Person = PersonS(string) | PersonI(int);
fun main() {
let p1 = PersonS("John");
let p2 = PersonI(20);
let arr_p = [p1, p2];
for p in arr_p {
match p {
PersonS(name) -> {
print(name, "\n");
}
PersonI(age) -> {
print(age, "\n");
}
}
}
let a = 10;
match a {
10 -> {
print("a is 10\n");
}
else -> {
print("compiler is broken!\n");
}
}
}let tuple = (10, 20,);
let (a, b,) = tuple;Used inside loops for exiting or continuing to the next iteration.
Used inside functions to return a value.
Expressions involve operators, function calls, array access, and more.
Math operators: +, -, *, /, %. Comparison operators: ==, !=, >, <, >=, <=. Logical and bitwise operators are also supported.
The precedence of operators is listed below, from highest to lowest:
| Operator | Description |
|---|---|
() |
Parentheses |
[] |
Array access |
!, ~, - |
Logical NOT, bitwise NOT, unary minus |
*, /, % |
Multiplication, division, remainder |
+, - |
Addition, subtraction |
<<, >> |
Bitwise shift left, bitwise shift right |
& |
Bitwise AND |
^ |
Bitwise XOR |
| |
Bitwise OR |
&& |
Logical AND |
|| |
Logical OR |
==, != |
Equality, inequality |
<, <=, >, >= |
Comparison |
= |
Assignment |
let result = add(10, 20);let value = a[0];let newArray = make([int], 10);make is used for creating arrays, maps, and channels.
let c = make(chan<int>);
c <- 10;
let value = <-c;Check Channels.
Channels facilitate communication between coroutines. Example:
fun sendVals(c: chan<int>, count: int, id: int) {
let i = 0;
while i < count {
c <- i;
i = i + 1;
}
}
fun recvVals(c: chan<int>, count: int, id: int) {
let i = 0;
while i < count {
print(<-c, " - ", id, "\n");
i = i + 1;
}
}
fun main() {
let i = 0;
while i < 100 {
let a = make(chan<int>, 1000);
sahl sendVals(a, 10000, i);
sahl recvVals(a, 10000, i);
i = i + 1;
}
}Sahl supports threads. In the virtual machine, threads are implemented as coroutines.
The sahl keyword is used for running a function in a new coroutine.
In the virtual machine, the main thread does not exit until all other threads have exited.
But when compiled to executable, the main thread exits immediately after spawning other threads and something like semaphores is needed to prevent the main thread from exiting.
Example:
fun printn(n: int) {
for i in 0..10 {
print(n, "\n");
}
}
fun main() {
for i in 0..100 {
sahl printn(i);
}
}The extern keyword is used for importing external c functions. Example:
// prog.sahl
extern fun exp(a: double) -> double {}
fun main() {
let a = 10.0;
let b = exp(a);
print(b, "\n"); // 22026.465795
}compile with:
./frontend/target/release/sahl file.sahl -n 2>exe.ll
clang -lm -O3 rt.c exe.ll math.c -o exe./exeThe sahl keyword runs a function in a new coroutine.
Explore more examples in the samples folder. Happy coding in Sahl!