Velo

Systems & interop

Standard Library

Boolean Extensions

Extension functions for boolean type:

import "std/bool"

bool flag = true
str s = flag.str()  # "true" or "false"
int i = flag.int()  # 1 or 0
bool neg = !flag  # logical NOT — use the ! operator

bool.str() is a compiler built-in, available without any import; import "std/bool" is what adds .int().

Integer Extensions

Extension functions for integer type:

import "std/int"

int x = -42
int absVal = x.abs()  # 42
str hex = (255).format(16)  # "ff"  — format(radix), radix 2..36
str bin = (10).format(2)  # "1010"

String Extensions

Extension functions for string type:

import "std/str"

str text = "Hello"
array[byte] bytes = text.bytes()  # [72, 101, 108, 108, 111]

Array Extensions

Extension functions for array type:

import "std/array"

array[byte] bytes = new array[byte]{72, 101, 108, 108, 111}
str text = bytes.str()  # "Hello"

Both extensions enable roundtrip conversion: text.bytes().str() == text.

The classes below — Terminal, Time, Http, FileSystem, Socket — are native classes provided by the runtime, so using them needs no import; the compiler knows their types from the registration. Just construct one. The examples use term as the conventional name for a Terminal instance.

Terminal

Class for terminal operations:

Terminal term = new Terminal()
term.print("Hello")  # Output without newline
term.println("World")  # Output with newline
str input = term.input()  # Read string from console

Time

Class for time operations:

Time time = new Time()
time.sleep(1000)  # Sleep for 1000 milliseconds
int unixTime = time.unix()  # Unix timestamp in seconds
int t = time.millis()  # monotonic milliseconds (for measuring elapsed time)

Http

Class for making HTTP requests:

Http http = new Http()
str response = http.get("https://example.com")
int status = http.statusCode()

# POST request
str jsonBody = "{\"key\": \"value\"}"
str postResponse = http.post("https://api.example.com/data", jsonBody, "")

FileSystem

Class for file system operations:

FileSystem fs = new FileSystem()

# Reading and writing strings
fs.write("file.txt", "Content")
str content = fs.read("file.txt")
fs.append("file.txt", "\nMore content")

# Reading and writing byte arrays
import "std/str"
array[byte] data = "binary data".bytes()
fs.writeBytes("file.bin", data)
array[byte] loaded = fs.readBytes("file.bin")
fs.appendBytes("file.bin", data)

# Checks
bool exists = fs.exists("file.txt")
bool isFile = fs.isFile("file.txt")
bool isDir = fs.isDir("directory")

# Directory operations
fs.mkdir("new_dir")
array[str] files = fs.list(".")

# File operations
fs.copy("source.txt", "dest.txt")
fs.move("old.txt", "new.txt")
fs.delete("file.txt")

# Information
int fileSize = fs.size("file.txt")

Socket

Class for TCP socket communication. Supports both client and server modes.

Client

Socket sock = new Socket()
sock.connect("127.0.0.1", 9876)

sock.writeLine("Hello!")
str reply = sock.readLine()

sock.close()

Server

Socket srv = new Socket()
srv.bind(9876)

Socket client = srv.accept()  # blocks until a client connects
str msg = client.readLine()
client.writeLine("Echo: " + msg)

client.close()
srv.close()

Full API Reference

MethodSignatureDescription
connect(str host, int port) voidConnect to a remote host
bind(int port) voidBind and listen on a port
accept() SocketAccept an incoming connection (blocking)
write(str data) voidSend a string
writeLine(str data) voidSend a string followed by a newline
writeBytes(array[byte] data) voidSend a byte array
readLine() strRead a line (blocking, strips newline)
read(int size) strRead up to size characters
readBytes(int size) array[byte]Read up to size bytes
available() intBytes available without blocking
connected() boolCheck if socket is connected
close() voidClose the socket
remoteAddress() strRemote peer IP address
remotePort() intRemote peer port
setTimeout(int millis) voidSet timeout for blocking operations

Map

A generic hash map (Map[K, V]) with separate chaining and automatic resizing. Supports operator overloading for bracket-based access.

Creating and Populating

import "std/map"

Map[str, int] ages = new Map[str, int]()

# Operator syntax
ages["Alice"] = 30
ages["Bob"] = 25

# Method syntax
ages.put("Charlie", 35)

Lookup

# operator [] returns V directly — it is at(), and raises on a missing key
int age = ages["Alice"]  # 30
int same = ages.at("Alice")  # 30 — [] is defined as at()

# get() returns ptr[V] — null if key is not found
ptr[int] val = ages.get("Alice")
if (val != null) {
    int a = val.val()
}

# getOrDefault() returns V directly, with a fallback
int eveAge = ages.getOrDefault("Eve", 0)  # 0

ages["Eve"] and ages.at("Eve") raise an Error with kind ERR_BOUNDS when the key is absent — a missing key is out of range the same way a[9] is on a two-element array. It is catchable like any other error, but the accessors above are the direct way to handle a key that may not be there:

Map[str, int] counts = new Map[str, int]()

# not this — it raises ERR_BOUNDS the first time a word is seen
# counts[word] = counts[word] + 1

counts[word] = counts.getOrDefault(word, 0) + 1

Checking and Conditional Insert

bool has = ages.key("Bob")  # true
bool empty = ages.empty()  # false
int count = ages.len  # number of entries (a field — no parentheses)

# putIfAbsent — inserts only if key is missing, returns true if inserted
bool added = ages.putIfAbsent("Diana", 28)  # true
bool again = ages.putIfAbsent("Diana", 99)  # false, value stays 28

Removing Entries

bool removed = ages.del("Charlie")  # true
bool noop = ages.del("Charlie")  # false (already gone)

Iterating

array[str] k = ages.keys()  # array of all keys
array[int] v = ages.vals()  # array of all values

int i = 0
while (i < k.len()) {
    # process k[i] and v[i]
    i = i + 1
}

Clearing

ages.clear()
# ages.len is 0, ages.empty() is true

Automatic Resizing

The map starts with capacity 16 and doubles when the load factor exceeds 75%. All entries are rehashed into the new table automatically. This is transparent — no API changes are needed:

Map[int, int] big = new Map[int, int]()
int n = 0
while (n < 100) {
    big[n] = n * n
    n = n + 1
}
# capacity has grown automatically, all 100 entries are accessible

Full API Reference

Method / OperatorSignatureDescription
operator [](K key) VLookup by key
operator []=(K key, V value) voidInsert or update
put(K key, V value) voidInsert or update
get(K key) ptr[V]Lookup (null if missing)
getOrDefault(K key, V defaultValue) VLookup with fallback
at(K key) VGet value directly (error if missing)
key(K key) boolCheck key existence
val(V value) boolCheck if value exists
putIfAbsent(K key, V value) boolInsert if missing, returns true if inserted
del(K key) boolRemove entry, returns true if found
keys() array[K]All keys as array
vals() array[V]All values as array
arr() array[tuple[K, V]]All entries as array of tuples
clear() voidRemove all entries
empty() boolCheck if map has no entries
lenint (field)Number of entries

Random

Random is a pure-Velo reimplementation of java.util.Random — the same 48-bit linear congruential generator (multiplier 0x5DEECE66D, addend 0xB, modulus 2^48), so a given seed produces exactly the same sequence as the JVM.

import "std/random"

Random r = new Random(42)  # seed it like java.util.Random(long)
r.nextInt()  # -1170105035 (same as the JVM)
r.nextIntBound(100)  # uniform in [0, 100)
r.nextBoolean()  # true / false
r.nextFloat()  # float in [0, 1)
r.setSeed(12345)  # reseed in place

Velo has no double, so the nextDouble and nextGaussian parts of java.util.Random are intentionally omitted (as is nextLong — the generator is written with 32-bit int arithmetic). Because Velo has no method overloading, the bounded draw is named nextIntBound rather than overloading nextInt.

Full API Reference

MethodSignatureDescription
constructor(int seed)Seed the generator (like java.util.Random(long))
setSeed(int seed) voidReseed in place
nextInt() intNext pseudorandom 32-bit int (full range)
nextIntBound(int bound) intUniform int in [0, bound)
nextBoolean() boolNext pseudorandom bool
nextFloat() floatUniform float in [0, 1)

Encoding & Compression

Pure-Velo modules for byte-level work. Each exposes a class and a ready-made global instance you can use directly after importing:

import "std/base64"
import "std/crc32"
import "std/deflate"
import "std/zip"
import "std/str"  # for .bytes()

# Base64 — text in, text out
str encoded = base64.encode("hello")  # "aGVsbG8="
str decoded = base64.decode(encoded)  # "hello"

# CRC-32 checksum of a byte array
int sum = crc32.checksum("hello".bytes())  # 907060870

# Raw DEFLATE compression (inflate with any standard zlib, wbits = -15)
array[byte] packed = rawDeflate.compress("hello".bytes())

# Build a single-entry ZIP archive
array[byte] archive = zip.create("hello".bytes(), "greeting.txt")
ModuleGlobalMethod
std/base64base64encode(str) str, decode(str) str
std/crc32crc32checksum(array[byte]) int
std/deflaterawDeflatecompress(array[byte]) array[byte]
std/zipzipcreate(array[byte] data, str entryName) array[byte]