Nix with flakes enabled is the only supported way to build and develop Vampa. It provides the exact Rust toolchain and LLVM the project expects, so there are no system dependencies to install by hand.
Enter a development shell with everything on PATH (Rust, LLVM, just):
nix developOr build the compiler directly:
nix build # produces ./result/bin/vamc
nix run -- ./test.vamFor an automatic shell that loads whenever you cd into the project, install
direnv and create a .envrc (it is git-ignored):
echo "use flake" > .envrc
direnv allowRecipes live in the justfile and run inside the Nix shell:
just build # cargo build
just test # cargo test
just run ./test.vam # compile and run a program
just fmt # format every file via `nix fmt`
just check # nix flake checkSee Thread with programs that compile and run.
Write your program:
# test.vam
fun three returning i32 = 3;
apply three
Compile and run it. vamc emits a native object file and links it into an
executable next to the source (./test for ./test.vam). A program's result is
its exit code:
just run ./test.vamSince the MVP will only deal with integers, I can skip implementing type-checking because everything is an i32. Perhaps I will need to implement a type for functions.
It should include:
- Comments
- All the arithmetic operations
- The ability to declare and define variables of type
i32 - The ability to declare functions (with and without body brackets)
- The ability to call functions
- No concept of scope
- This is not a permanent feature and scope should eventually be implemented
- A single hash map for all variables
- Variable references
The following program should compile and run:
let first: i32 = 20;
let second: i32 = 22;
fun sum of a: i32 and b: i32 returning i32 = + a b;
fun sum_with_brackets of a: i32 and b: i32 returning i32 = { + a b };
apply sum first second; # 42
apply sum 10 12; # 22
apply sum { 10 } 10; # 20
apply sum { + 2 2 } 5; # 9
- Expression-oriented
- Immutable by default
- Strictly typed
- Supporting type inference
- Compiled using LLVM as a backend
Vampa is case-sensitive and uses the Unicode character set.
- Comments can be inline or block
- Inline comments
- Block commments
# An inline comment
#[
# Hey there
# This is my block comment
#
# #[
# # This is a nested block comment
# # Hey there
# #]
#]
- Statements are terminated by a semicolon
- Makes use of curly brackets
{}for blocks - Identifiers must start with a letter and must not include
: - Variables are declared using
let- They must be initialized at the time of their declaration
- They are either in the scope of their module or in the scope of a block
let poem = "The revery alone will do, if bees are few";
- Functions are declared using
ofto initiate a list of arguments, andandto separate arguments, and then=to start the body of the function, which can have a body{}or a body without brackets
# Using a body without brackets
fun sum of first_number and second_number = + first_number second_number;
# Using a body with brackets, implicitly returning the last expression
fun sum of first_number and second_number = { + first_number second_number };
- Functions calls are preceded by
applyand arguments in function calls are delimited with spaces:
let aggregate = apply sum 5 7;
- Blocks can be used to eliminate ambiguity:
let aggregate = apply sum 5 { sum 7 8 };
- Type hints are indicated using a colon
:, must be placed next to the identifier they refer to, and can be used:- Next to variable identifiers to indicate their type
- Next to function identifiers to indicate their return type
let poem: string = "The revery alone will do, if bees are few";
fun sum of first: i32 and second: i32 returning i32 = + first second;
- Types are declared using the
typekeyword.
type Uuid = string;
- Generic types are indicated using square brackets
[]:
type Five[T] = [5 of T];
- Boolean:
trueandfalse
| Length | Signed | Unsigned |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
f32f64
truefalse
It's four bytes in size.
char
string
[char, i32]: a tuple of acharand ani32
[5 of char]: an array of length 5 containingchars
These are used in prefix position and can be combined using curly brackets {} to indicate precedence explicitly.
+-/%*
- Any variable starting with any symbol that's not a letter
- All the types listed above
andapplyfunletofreturningtype