Documents every built-in function, type, and method available in any Capa program, no imports required.
| Type | Size/Range | Notes |
|---|---|---|
Int |
64-bit signed | Arithmetic does not check for overflow |
Float |
64-bit IEEE 754 | |
String |
UTF-8 | Immutable |
Bool |
true / false |
|
Char |
Unicode code point | At runtime, a str of length 1 |
Unit |
() |
"Empty" type for functions with no return value |
| Method | Type | Description |
|---|---|---|
length() |
Int |
Number of characters |
is_empty() |
Bool |
True if the string is empty |
to_upper() |
String |
Convert to upper case |
to_lower() |
String |
Convert to lower case |
trim() |
String |
Strip whitespace at both ends |
trim_start() |
String |
Strip leading whitespace only |
trim_end() |
String |
Strip trailing whitespace only |
contains(sub: String) |
Bool |
Substring is present |
starts_with(s: String) |
Bool |
|
ends_with(s: String) |
Bool |
|
split(sep: String) |
List<String> |
Split by separator |
replace(old: String, new: String) |
String |
Replace every occurrence |
Mutable homogeneous list. Construct with the literal [a, b, c] or by
push on a let/var. Cross-statement inference: let xs = []
infers the type from the first push.
| Method | Type | Description |
|---|---|---|
length() |
Int |
Number of elements |
is_empty() |
Bool |
|
push(x: T) |
() |
Append at the end (mutation) |
contains(x: T) |
Bool |
|
first() |
Option<T> |
First element or None |
last() |
Option<T> |
Last element or None |
get(i: Int) |
Option<T> |
Safe indexed access |
map<U>(f: Fun(T) -> U) |
List<U> |
Transform each element |
filter(p: Fun(T) -> Bool) |
List<T> |
Keep elements that match |
fold<U>(init: U, f: Fun(U, T) -> U) |
U |
Reduce to a single value |
find(p: Fun(T) -> Bool) |
Option<T> |
First element matching p |
find_index(p: Fun(T) -> Bool) |
Option<Int> |
Index of first element matching p |
sorted_by(cmp: Fun(T, T) -> Int) |
List<T> |
Fresh sorted copy. cmp(a, b) returns negative / 0 / positive as in C's qsort. Stable. |
Index access: xs[i] (no bounds checking, use get(i) for safe access).
a..b (exclusive of b) and a..=b (inclusive) produce a
List<Int> materialised from the half-open / closed integer range.
Both endpoints must be Int. Float endpoints are deliberately
excluded.
for i in 0..10 // 0, 1, 2, ..., 9
stdio.println("${i}")
for i in 1..=5 // 1, 2, 3, 4, 5
stdio.println("${i}")
let n = 4
let xs = (n - 1)..(n * 2) // 3..8, arithmetic endpoints
let evens = (0..10).filter(fun (x: Int) -> Bool => x % 2 == 0)
// ranges support the full List API
Range precedence sits between addition and comparison, so
1+2..5+3 parses as (1+2)..(5+3) and a..b == c..d as
(a..b) == (c..d). Range itself is non-associative, a..b..c is
a syntax error.
Hash map. Construct via new_map() with a required type annotation.
| Method | Type | Description |
|---|---|---|
length() |
Int |
|
is_empty() |
Bool |
|
get(k: K) |
Option<V> |
Returns the value if the key exists |
set(k: K, v: V) |
() |
Insert/update (mutation) |
contains_key(k: K) |
Bool |
|
keys() |
List<K> |
|
values() |
List<V> |
let m: Map<String, Int> = new_map()
m.set("a", 1)
match m.get("a")
Some(n) -> stdio.println("a = ${n}")
None -> stdio.println("not found")
Set of unique elements. Construct via new_set() with a type annotation.
| Method | Type | Description |
|---|---|---|
length() |
Int |
|
is_empty() |
Bool |
|
add(x: T) |
() |
Add (no-op if duplicate) |
remove(x: T) |
() |
Remove (no-op if absent) |
contains(x: T) |
Bool |
|
to_list() |
List<T> |
Convert to a list |
Built-in sum type:
type Option<T> =
Some(T)
None
| Method | Type | Description |
|---|---|---|
is_some() |
Bool |
|
is_none() |
Bool |
|
unwrap_or(default: T) |
T |
Return value or default |
map<U>(f: Fun(T) -> U) |
Option<U> |
Transform if Some |
and_then<U>(f: Fun(T) -> Option<U>) |
Option<U> |
Monadic bind |
ok_or<E>(err: E) |
Result<T, E> |
Convert to a Result |
Built-in sum type for error handling:
type Result<T, E> =
Ok(T)
Err(E)
| Method | Type | Description |
|---|---|---|
is_ok() |
Bool |
|
is_err() |
Bool |
|
unwrap_or(default: T) |
T |
Return value or default |
map<U>(f: Fun(T) -> U) |
Result<U, E> |
Transform the success value |
and_then<U>(f: Fun(T) -> Result<U, E>) |
Result<U, E> |
Monadic bind |
map_err<F>(f: Fun(E) -> F) |
Result<T, F> |
Transform only the error |
The ? operator: automatically propagates Err in functions that
return Result:
fun read_and_process(fs: Fs) -> Result<Int, IoError>
let content = fs.read("x.txt")? // if Err, returns immediately
return Ok(content.length())
Built-in sum type for JSON representation:
type JsonValue =
JNull
JBool(Bool)
JNum(Float)
JStr(String)
JArr(List<JsonValue>)
JObj(Map<String, JsonValue>)
| Method | Type | Description |
|---|---|---|
is_null() |
Bool |
|
as_bool() |
Option<Bool> |
Some(b) if JBool(b) |
as_num() |
Option<Float> |
Some(n) if JNum(n) |
as_string() |
Option<String> |
Some(s) if JStr(s) |
as_array() |
Option<List<JsonValue>> |
Some(xs) if JArr(xs) |
as_object() |
Option<Map<String, JsonValue>> |
Some(m) if JObj(m) |
| Function | Type |
|---|---|
parse_json(s: String) |
Result<JsonValue, String> |
to_json(j: JsonValue) |
String |
| Function | Type | Notes |
|---|---|---|
parse_int(s: String) |
Option<Int> |
Returns None on invalid input |
parse_float(s: String) |
Option<Float> |
Same for floats |
to_float(i: Int) |
Float |
Total, every Int has an exact Float representation |
to_int(f: Float) |
Int |
Truncates toward zero |
new_map() |
Map<?, ?> |
Requires let annotation to pin the types |
new_set() |
Set<?> |
Same |
Capa has no implicit numeric coercion, Float + Int is a type
error. Use to_float / to_int at the call site to make the
conversion explicit:
fun avg(sum: Float, count: Int) -> Float
return sum / to_float(count)
The two functions below cross the Capa/Python trust boundary. Both
require the Unsafe capability as the first argument.
| Function | Type |
|---|---|
py_import(unsafe: Unsafe, name: String) |
dynamic (untyped) |
py_invoke(unsafe: Unsafe, callable: ?, args: List<?>) |
dynamic (untyped) |
fun square_root(unsafe: Unsafe, x: Float) -> Float
let math = py_import(unsafe, "math")
return py_invoke(unsafe, math.sqrt, [x])
| Method | Type | Description |
|---|---|---|
print(s: String) |
() |
No newline |
println(s: String) |
() |
With newline |
eprintln(s: String) |
() |
To stderr |
read_line() |
Result<String, IoError> |
Read a line without \n |
| Method | Type | Description |
|---|---|---|
read(p: String) |
Result<String, IoError> |
Read the entire file |
write(p: String, c: String) |
Result<(), IoError> |
Write (overwrites) |
exists(p: String) |
Bool |
Check whether the path exists |
is_dir(p: String) |
Bool |
True if p exists and is a directory |
mkdir(p: String) |
Result<(), IoError> |
Create directory, including missing parents. Idempotent: re-creating an existing directory is Ok. |
list_dir(p: String) |
Result<List<String>, IoError> |
Entry names (basenames), alphabetically sorted. |
restrict_to(prefix: String) |
Fs |
Attenuate: a fresh Fs allowing only paths under prefix. Monotonic. |
allows(path: String) |
Bool |
Test whether the current Fs would permit path. |
is_dir, exists, and allows all use the same fail-closed-as-
absent convention: a denied path reports false, indistinguishable
from a path that does not exist. The cap therefore does not leak
the existence of paths outside its allowed set.
Both the stored allowed prefixes and the queried paths are passed
through os.path.realpath (resolves .. / . segments and
follows symlinks) before comparison; the containment check is
path-aware, not string-prefix. Traversal patterns
(data/../etc/passwd) and symlinks pointing outside the prefix
are both denied. A TOCTOU race between allows() and the
underlying open() remains possible against an actively
hostile attacker; fully closing it requires open-at-dirfd
semantics, planned for a later iteration.
| Method | Type | Description |
|---|---|---|
get(name: String) |
Option<String> |
Environment variable |
args() |
List<String> |
Command-line arguments |
| Method | Type | Description |
|---|---|---|
now_secs() |
Float |
Unix time in seconds |
now_monotonic() |
Float |
Monotonic time |
sleep(seconds: Float) |
() |
Pause execution |
| Method | Type | Description |
|---|---|---|
int_range(low: Int, high: Int) |
Int |
Integer in [low, high) |
float_unit() |
Float |
Float in [0, 1) |
| Method | Type | Description |
|---|---|---|
restrict_to(host: String) |
Net |
Attenuate: return a fresh Net whose authority is the intersection of the current allowed-host set with {host}. Monotonic, restrictions only narrow. |
allows(host: String) |
Bool |
Query the current restriction set; performs no I/O. |
get(url: String) |
Result<String, IoError> |
Real HTTP GET (via urllib.request). Returns Err immediately if the URL's host is outside the current restriction set, before any system call. |
A Net received from main is unrestricted; restrictions accumulate
through restrict_to. The result of restrict_to is a fresh
capability instance and is bindable in a let/var, Capa relaxes
the "no capabilities in locals" rule specifically for method-call
results (which are necessarily fresh, not aliases of an existing
capability).
fun fetch(net: Net) -> Result<String, IoError>
return net.get("https://api.example.com/users")
fun main(net: Net, stdio: Stdio)
let api = net.restrict_to("api.example.com")
match fetch(api)
Ok(body) -> stdio.println(body)
Err(e) -> stdio.eprintln("${e}")
See examples/net_attenuation.capa for a fuller demonstration,
including the monotonic-narrowing property (chaining two disjoint
restrictions yields a Net that allows nothing).
Marker capability for crossing the Python boundary. Has no methods -
its only role is to gate py_import and py_invoke (see "Python
interoperability" above).
Libraries can declare their own capabilities with the capability
keyword. The declaration registers the name in the capability
discipline; any type that implements the capability becomes a valid
implementor.
capability SendEmail
fun send(self, to: String, subject: String, body: String) -> Result<Unit, IoError>
type SmtpMailer {
server: String,
net: Net // built-in cap as a field, allowed because
// SmtpMailer implements a user-defined cap
}
impl SendEmail for SmtpMailer
fun send(self, to: String, subject: String, body: String) -> Result<Unit, IoError>
// delegate to self.net under the hood
return Ok(())
// Factory that consumes the underlying built-in cap and produces the
// higher-level capability. Allowed return type even though SmtpMailer
// carries authority.
fun make_smtp_mailer(net: Net, server: String) -> SmtpMailer
return SmtpMailer { server: server, net: net.restrict_to(server) }
// Caller side: receive the capability by parameter (subtyping accepts
// SmtpMailer where SendEmail is expected because of the impl).
fun send_welcome(mailer: SendEmail, to: String) -> Result<Unit, IoError>
return mailer.send(to, "Welcome", "Hello!")
The discipline still applies: a let dup = mailer (plain identifier
alias of a cap-bearing value) is rejected; only call/method-call RHSs
produce fresh capability instances that can be bound. See
examples/user_capabilities.capa for a complete example.
Opaque type representing I/O errors. Available as a type parameter in
Result<T, IoError> and in pattern matching:
match fs.read("x.txt")
Ok(content) -> stdio.println(content)
Err(e) -> stdio.eprintln("error: ${e}")
IoError's string representation is human-readable, but its internal
contents are private.