Tracing
A tracing collector finds unreachable objects and frees them. Nothing to think about.
Antril is a compiled language with a modern syntax. Larva turns it into native executables, WebAssembly or portable libraries, and every project chooses how its memory is managed.
curl -fsSL https://www.antril.org/install.sh | sh
irm https://www.antril.org/install.ps1 | iex
For Windows, Linux and macOS · Other ways to install
import System;
into namespace People
{
public record class Person
{
public:
str Name;
i32 Age;
new(str Name, i32 Age);
}
Main()
{
Person ana = new Person("Ana", 31);
Person older = ana with { Age = 32 };
Console.WriteLine(ana);
Console.WriteLine(ana == new Person("Ana", 31));
if (ana is Person(var name, > 30))
Console.WriteLine(name + " is over 30");
}
}
larva run
Person { Name = Ana, Age = 31 }
true
Ana is over 30
The language
Every program below is complete, compiles with the current Larva, and prints what you see. Pick an idea:
import System;
into namespace Shapes
{
public interface IShape
{
Area() : f64;
Describe() : str => "a shape of area " + Area();
}
public base class Shape : IShape
{
public:
Area() : f64;
virtual Name() : str => "shape";
}
public class Circle : Shape
{
f64 radius;
public:
new(f64 radius) { this.radius = radius; }
override Area() : f64 => 3.14 * radius * radius;
override Name() : str => "circle";
}
public final class Square : Shape
{
f64 side;
public:
new(f64 side) { this.side = side; }
override Area() : f64 => side * side;
}
Main()
{
List<Shape> shapes = new List<Shape>();
shapes.Add(new Circle(1));
shapes.Add(new Square(2));
loop (Shape s in shapes)
Console.WriteLine(s.Name() + ": " + s.Area());
IShape i = new Square(3);
Console.WriteLine(i.Describe());
}
}
larva run
circle: 3.14
shape: 4
a shape of area 9
import System;
import System.Threading.Tasks;
into namespace Jobs
{
async Fetch(i32 id) : Task<i32>
{
await Task.Delay(10);
return id * 10;
}
async Total() : Task<i32>
{
i32 a = await Fetch(1);
i32 b = await Fetch(2);
return a + b;
}
async Tick(str name, i32 times) : Task
{
loop (i32 i = 0..times)
{
Console.WriteLine(name + " " + i);
await Task.Yield();
}
}
Main()
{
Console.WriteLine(Total().Result);
Task[] both = [Tick("a", 2), Tick("b", 2)];
Task.WhenAll(both).Wait();
}
}
larva run
30
a 0
b 0
a 1
b 1
import System;
import System.Reactive;
into namespace Ui
{
public class Cart
{
public:
reactive i32 items = 0;
reactive f64 price = 2.5;
computed f64 Total => items * price;
reacts Log()
{
Console.WriteLine("items: " + items);
}
}
Main()
{
Cart cart = new Cart();
Effect shown = effect { Console.WriteLine("total: " + cart.Total); };
cart.items = 2;
Reactive.Batch(() => { cart.items = 3; cart.price = 4.0; });
shown.Dispose();
cart.items = 10;
}
}
larva run
items: 0
total: 0
items: 2
total: 5
items: 3
total: 12
items: 10
import System;
MinMax(i32[] values) : (i32, i32)
{
i32 low = values[0], high = values[0];
loop (i32 v in values)
{
if (v < low)
low = v;
if (v > high)
high = v;
}
return (low, high);
}
Main()
{
(i32, i32) range = MinMax([4, 9, 1, 7]);
Console.WriteLine(range);
Console.WriteLine(range.Item2 - range.Item1);
(i32, str) pair = (1, "one");
if (pair is (1, var word))
Console.WriteLine(word);
Dictionary<(i32, i32), str> grid = new Dictionary<(i32, i32), str>();
grid[(0, 1)] = "a";
Console.WriteLine(grid[(0, 1)]);
}
larva run
(1, 9)
8
one
a
import System;
unsafe Fill(i32* p, i32 count, i32 value)
{
loop (i32 i = 0..count)
p[i] = value;
}
Main()
{
i32[] data = new i32[4];
unsafe
{
Fill(&data[0], data.Length, 9);
i32* second = &data[0] + 1;
*second = 1;
}
Console.WriteLine(data[0] + data[1] + data[2] + data[3]);
}
larva run
28
Memory your way
Each project picks its collector with one line of its .queen file. The same source compiles in every mode, and libraries built for different modes still work together.
A tracing collector finds unreachable objects and frees them. Nothing to think about.
Objects are freed the moment their last reference goes, and destructors run right then.
Everything a region { } made is freed together when it closes. Escapes are build errors.
You free each object with delete, in unsafe code, when you know best.
import System;
into namespace Mem
{
public class Resource
{
str name;
public:
new(str name) { this.name = name; }
destroy() { Console.WriteLine("close " + name); }
}
Main()
{
region
{
Resource a = new Resource("a");
Resource b = new Resource("b");
Console.WriteLine("leaving the region");
}
Console.WriteLine("end");
}
}
queen 1.0;
chunk PROJ:
name: Mem,
type: exe
chunk BUILD:
gc: arena
larva run
leaving the region
close b
close a
end
&T and &mut T references with an optional borrow checkerOne toolchain, many targets
Larva compiles through one intermediate form, Larva HIR, to the back end you choose.
LLVM at -O3: optimized native executables for your machine.
--backend x64: Larva’s own back end compiles faster while you iterate.
--target wasm or wasm-llvm: the same program in the browser.
larva lib writes a .dll that any language on Larva can use.
larva build -o hello.exe hello.ant
larva build --backend x64 -o hello.exe hello.ant
larva build --target wasm-llvm -o hello.js hello.ant
larva lib -o Geo.dll geo.ant
Native libraries in minutes
Declare a function with [Import] and call it. For a whole library, larva bind reads its exports and a C header or a short description, and writes a typed binding.
.dll, .so and .dyliblarva bind kernel32.dll kernel32.bind --source Kernel32.ant
Kernel32Bindings.dll: Kernel32 with 4 function(s) of kernel32.dll
Kernel32.ant: Antril source
import System;
import System.Runtime.InteropServices;
into namespace Native
{
[Import("kernel32.dll")]
GetCurrentProcessId() : u32;
[Import("kernel32.dll", "lstrlenW")]
WideLength(String<u16> text) : i32;
Main()
{
Console.WriteLine(GetCurrentProcessId() > 0);
Console.WriteLine(WideLength(new String<u16>(Unicode.ToUtf16("hello"))));
}
}
A package ecosystem
Every package is hashed and can be signed by its author. larva hive add Author/Name adds one to your project.
No package is published yet. Yours could be the first.
Publish a packageWhen packages start depending on each other, the most used ones show up here.
Using packagesBuilt for editors
The VS Code extensions bring Larva’s language server to your editor: the same compiler, as you type.
.queen project files that apply as you saveLanguages on Larva
Larva compiles any language that has a language pack. Packs are signed by their authors and by the registry, and share the standard library, the back ends and Hive.
From the community
These spaces are placeholders until the first community quotes are in. Building something with Antril? Tell us in the forum.
A quote from someone building with Antril, Larva or Hive will appear here.
A quote from someone building with Antril, Larva or Hive will appear here.
A quote from someone building with Antril, Larva or Hive will appear here.
Install Larva, create a project and run it in under a minute.
larva new Console-App Hello --lang antril