Dependencies are:
llvmenv
, which you can install withcargo install llvm
libssl-dev
on Debian oropenssl
on Arch Linux
Other things I needed on Ubuntu 18:
lib32z1-dev
, available throughapt
To build, follow these setup instructions and run:
cargo build
See Thread with programs that compile and run.
Write your program:
# test.vam
fun three returning i32 = 3;
apply three
Run it:
cargo run --bin vamc ./test.vam && lli ./test.o
Since 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
of
to initiate a list of arguments, andand
to 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
apply
and 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
type
keyword.
type Uuid = string;
- Generic types are indicated using square brackets
[]
:
type Five[T] = [5 of T];
- Boolean:
true
andfalse
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 |
f32
f64
true
false
It's four bytes in size.
char
string
[char, i32]
: a tuple of achar
and ani32
[5 of char]
: an array of length 5 containingchar
s
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
and
apply
fun
let
of
returning
type