Install
$ agentstack add skill-martian56-raven-language-skill-raven-language-skill ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Raven Language (v2)
Raven v2 is a statically-typed, ahead-of-time compiled language implemented in Rust. Source lowers through a resolver, type checker, HIR, and a monomorphizing MIR, then a Cranelift backend emits a native binary. Memory is managed by a tracing garbage collector. The syntax reads like a blend of Rust and Swift, with local type inference, no semicolons, traits, generics, sum types, and pattern matching. The single most useful thing this skill does is steer you away from the non-obvious pitfalls so the first version of your code parses, type-checks, and links.
> v2 is a clean break from v1. If you find old material mentioning elseif, C-style for loops, int/string lowercase types, format("{}", x), import math;, or main(); at the bottom of a file, that is v1 and does not apply here.
When to read what
- This file: read every time. The pitfalls and templates cover most tasks.
references/builtins.md: the always-available functions and the methods onString,List,Map,Set.references/stdlib.md: per-module API forstd/io,std/string,std/collections,std/math,std/iter,std/fs,std/time,std/json, and more.references/rvpm.md: starting a project,rv.toml, GitHub-direct packages, theravenandrvpmCLIs.references/grammar.md: exact lexical and grammar rules when something parses surprisingly.
The stdlib source lives in stdlib/std/*.rv in the Raven repo and is written in Raven itself, so reading it is the authoritative answer for any signature.
Pitfalls to internalise
These are the mistakes that ruin first-try compilation. Burn them in.
- No semicolons. Statements end at the newline. Do not terminate lines with
;. - Types are PascalCase.
Int,Float,Bool,String,Char,Unit. There is noint/string.Unitis the no-value type (the implicit return). - Type annotations are optional. Local inference works:
let x = 5infersInt. Annotate when you want to be explicit or when inference can't tell (let xs: List = []). Function parameters and return types are still written out. letis mutable; there is nolet mut. Reassign freely. Compound assignment works:+= -= *= /= %=.constis for immutable compile-time constants and works both as a local (const X = 5) and at module level (const MAX: Int = 100).- Logical operators are
&&,||,!. The wordsand/or/notare NOT operators. else ifis two words (v1'selseifis gone).ifis also an expression:let s = if x > 0 { "pos" } else { "neg" }.foris range/iterator based.for i in 0..10 { }(exclusive),for i in 1..=10 { }(inclusive),for item in list { }.while cond { }andloop { }exist.breakandcontinuework.- String interpolation is
"${expr}". The expression can be arbitrary: a nested string literal ("${a.concat("y")}"), a macro call ("${square!(5)}"), and a struct value that derivesToString("${p}") all interpolate directly. Stringlength is.length(), not.len()..len()type-checks but fails in codegen.List/Map/Setuse.len(). String methods (.to_upper(),.trim(),.split(),.concat(), …) requireimport std/string.- No
null. Absence isOption(sugarT?) withSome(x)/None. Fallible results areResultwithOk(x)/Err(e)and the?operator.Some,None,Ok,Errare in scope without imports. - Enum variants are constructed qualified:
Shape.Circle(2.0),Color.Red. Inmatch, the patterns are bare:Circle(r) -> ....matchis exhaustive. - No visibility modifiers. Every top-level
fun/struct/enum/traitis importable. There is noexportand nopub. fun main()is the entry point. Define it; do NOT callmain()yourself. There is no top-level statement execution.- Prefer selector imports for free functions.
import std/fs { write }thenwrite(path, data)is the form that always works. Module-qualified access (import std/fsthenfs.exists(...)) works for some runtime-backed modules but not all (import std/maththenmath.sqrt(...)fails), so reach for the selector form. Types (Map) and methods (.to_upper) come in throughimport std/collections { Map }/import std/string. matchonStringliteral patterns works.match s { "a" -> ..., _ -> ... }matches as expected, and strings support `` ordering.- Reading module-level bindings works; mutating them does not. A top-level
let/constis readable from any function (let greeting: String = "hi"), but reassigning a module-level binding from a function mis-compiles (binop lhs used a Unit value). For mutable state, keep it inside functions, thread it through parameters, or hold it in a struct you pass around.
Anatomy of a Raven file
// imports: std modules by name, locals and packages by quoted path
import std/io { println }
import std/collections { Map }
import "./board" // local ./board.rv
import "github.com/user/raven-json" { parse } // GitHub-direct package
// a trait
trait Display {
fun show(self) -> String
}
// a struct + an impl of the trait + inherent methods
struct Point {
x: Float,
y: Float,
}
impl Display for Point {
fun show(self) -> String = "(${self.x}, ${self.y})"
}
impl Point {
fun magnitude(self) -> Float = sqrt(self.x * self.x + self.y * self.y)
}
import std/math { sqrt }
// a free function (single-expression body)
fun midpoint(a: Point, b: Point) -> Point =
Point { x: (a.x + b.x) / 2.0, y: (a.y + b.y) / 2.0 }
// entry point: defined, never called by you
fun main() {
let p = Point { x: 3.0, y: 4.0 }
println("mag = ${p.magnitude()}")
println(p.show())
}
Implicit rules:
- Imports:
import std/ { names }for the bundled stdlib;import "./rel"for a sibling file;import "github.com/user/repo" { names }for a package fetched by rvpm. Selectors bring the names into scope unqualified. - No entry call: the runtime calls
mainfor you. - Single-expression bodies:
fun f(...) -> T =is shorthand for{ return }. - Trailing commas are allowed in struct definitions/literals and collection literals.
Templates
Working code you can adapt. These compile.
Variables, control flow
fun main() {
let total = 0
for i in 1..=10 {
if i % 2 == 0 {
total += i
}
}
let label = if total > 20 { "big" } else { "small" }
print("${total} is ${label}")
}
Collections and iterators
import std/io { println }
import std/collections { Map }
import std/iter { collect, fold }
fun main() {
let nums = [1, 2, 3, 4, 5, 6]
println("len = ${nums.len()}, first = ${nums[0]}")
// lazy pipeline: consume with collect / fold / count
let doubledEvens: List =
collect(nums.iter().filter(fun(x: Int) -> Bool = x % 2 == 0).map(fun(x: Int) -> Int = x * 2))
println("count = ${doubledEvens.len()}")
let sum = fold(nums.iter(), 0, fun(acc: Int, v: Int) -> Int = acc + v)
println("sum = ${sum}")
let tally: Map = Map.new()
tally.set("a", 1)
match tally.get("a") {
Some(n) -> println("a = ${n}"),
None -> println("missing"),
}
}
Struct, trait, dynamic dispatch
trait Shape {
fun area(self) -> Float
}
struct Circle { r: Float }
struct Square { side: Float }
impl Shape for Circle {
fun area(self) -> Float = 3.14159 * self.r * self.r
}
impl Shape for Square {
fun area(self) -> Float = self.side * self.side
}
fun describe(s: dyn Shape) {
print("area = ${s.area()}")
}
fun main() {
describe(Circle { r: 2.0 })
describe(Square { side: 3.0 })
}
Note: List (a heterogeneous list of trait objects) is not supported in this release. Pass trait objects to dyn-typed parameters or assign to a dyn-typed local.
Enums, match, Option, Result, ?
enum Shape {
Circle(Float)
Rectangle(Float, Float)
}
fun area(s: Shape) -> Float =
match s {
Circle(r) -> 3.14159 * r * r,
Rectangle(w, h) -> w * h,
}
fun checked_div(a: Int, b: Int) -> Result {
if b == 0 {
return Err("divide by zero")
}
return Ok(a / b)
}
fun halve_then_div(a: Int, b: Int) -> Result {
let q = checked_div(a, b)? // ? propagates Err, unwraps Ok
return Ok(q / 2)
}
fun main() {
print("${area(Shape.Circle(2.0))}")
match halve_then_div(20, 5) {
Ok(v) -> print("ok ${v}"),
Err(e) -> print("err ${e}"),
}
}
Generics with a trait bound
trait Describe {
fun describe(self) -> String
}
struct Dog {}
impl Describe for Dog {
fun describe(self) -> String = "a dog"
}
fun announce(x: T) {
print("this is ${x.describe()}")
}
fun main() {
announce(Dog {})
}
defer (LIFO, runs at function exit)
fun main() {
let log = [1]
defer log.push(3) // runs second
defer log.push(2) // runs first
print("len now ${log.len()}")
}
Concurrency: spawn + channels
import std/sync { channel, channel_buffered, yield_now }
fun main() {
let ch = channel()
spawn(fun() -> Unit {
let i = 1
while i Unit {
wg.done()
})
wg.wait()
// select_recv: block on several channels, lowest ready index wins. The
// SelectResult is { index, value } (index -1 if the list was empty).
let a = channel()
let b = channel()
spawn(fun() -> Unit { a.send(7) })
let r = select_recv([a, b])
print("chan ${r.index} -> ${r.value}")
}
Channels, wait groups, and select sets hold runtime registry entries with no destructor; call .free() (or select_recv frees its own set) when you are done with one to avoid leaking the entry.
Metaprogramming: derive + macros + reflection
@derive(Eq, Hash, ToString, Debug)
struct Point { x: Int, y: Int }
macro square { ($x:expr) => { ($x) * ($x) } }
fun main() {
let p = Point { x: 1, y: 2 }
print(p.to_string()) // Point { x: 1, y: 2 }
print("${square!(5)} fields=${field_names().len()}")
}
Derivable traits: Eq, Hash, ToString, Debug, and Ord. @derive(Ord) adds compare(self, other) -> Int (negative / zero / positive), comparing structs field-by-field in declaration order and enums by variant order then payload. Pair it with import std/cmp { sort } to sort a List:
import std/cmp { sort }
@derive(Ord)
struct Version { major: Int, minor: Int }
fun main() {
let vs = sort([Version { major: 1, minor: 2 }, Version { major: 1, minor: 0 }])
print("${vs[0].minor}") // 0
}
C FFI
import std/ffi { alloc, free, load, store }
extern "C" {
fun abs(x: CInt) -> CInt
fun strlen(s: CStr) -> CSize
}
fun main() {
print("${abs(-7)}")
let len = strlen(c"hello") // c"..." is a C string literal
print("${len}")
let buf = alloc(2)
store(buf, 42)
print("${load(buf)}")
free(buf)
}
Built-in cheatsheet
Always available, no import. See references/builtins.md for details.
| Need | Use | | --------------------------- | ---------------------------------------------------- | | Print a line | print("...") (interpolate with ${expr}) | | Print via stdlib | println(...) after import std/io { println } | | List length / element | xs.len(), xs[i], xs.push(v) | | Iterator from a list | xs.iter() then .map/.filter, consumed by std/iter | | Option / Result values | Some(x), None, Ok(x), Err(e) | | Goroutine | spawn(fun() -> Unit { ... }) | | Compile-time reflection | type_name(), field_names() | | Raw memory byte | __str_byte_at(s, i) (low-level; prefer std/string) |
Stdlib at a glance
Bundled into the compiler; import with import std/ { names }. See references/stdlib.md.
| Module | What's there | | ----------------- | ----------------------------------------------------------------------- | | std/io | print, println | | std/string | merges String methods: to_upper, to_lower, trim, split, concat, contains, replace, substring, length, … | | std/fmt | string formatting: pad_left, pad_right, center, repeat, join, to_hex/to_binary/to_octal/to_radix, from_hex/from_radix, format_float, pad_int | | std/collections | Map, Set with constructors and methods | | std/iter | collect, fold, count over .iter().map(...).filter(...) pipelines | | std/math | sqrt, pow, pow_int, abs, min, max, pi, e, trig, … | | std/fs | read, write, append, exists, remove_file, list_dir, split_lines (all return Result where fallible) | | std/time | now, now_millis, format_timestamp, parse_timestamp | | std/json | JsonValue enum, parse, stringify | | std/sync | channel, channel_buffered, send/recv, yield_now, sleep_millis, Mutex (mutex, lock/unlock), WaitGroup (wait_group, add/done/wait), select_recv | | std/ffi | alloc, free, load, store, offset, is_null, null_ptr | | std/random | Rng (new, from_entropy, next_int, gen_range) | | std/cmp | min, max, clamp, sort, sorted_by (pairs with @derive(Ord)) | | std/http | get, post, put, delete, patch, request; serve_connection for a basic server | | std/net | connect, listen, dns_lookup, reachable | | std/tls | client TLS: connect(addr, server_name) (verified), connect_with + config() builder (add_ca_file, client_cert, insecure_skip_verify), upgrade(tcp_stream, server_name) for STARTTLS (Postgres/MySQL); TlsStream read/write/close. std/http already does https:// | | std/encoding | hex_encode, hex_decode, url_encode, base64 helpers | | std/env | get_env, has_env, get_env_or, args, arg_count, arg_at, exit, os_name, arch | | std/hash | fnv, djb, crc, checksum, combine | | std/path | join, basename, dirname, extension, stem, normalize, is_absolute | | std/process | run, run_with_input | | std/regex | compile and match against compiled patterns | | std/test | assertions for rvpm test: assert, assert_msg, assert_true/assert_false, assert_eq/assert_ne (generic), assert_eq_int/assert_eq_str/assert_eq_float, assert_some/assert_none/assert_ok |
If a name isn't here, read stdlib/std/.rv in the Raven repo. Note: a dependency package can also import std free functions (fixed in 2.0.2).
Running and project layout
my_project/
├── rv.toml # [package] / [dependencies] / optional [ffi], [fmt]
└── src/
└── main.rv # entry point — defines fun main(), not called manually
rvpm init my_project # scaffold in the current dir (--lib for a library, lib.rv)
rvpm new my_project # scaffold in a fresh my_project/ dir (--lib)
rvpm run # build src/main.rv and run it (forwards args: rvpm run -- a b)
rvpm build # compile to target/raven-out/, or type-check a lib.rv
rvpm test #
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [martian56](https://github.com/martian56)
- **Source:** [martian56/raven-language-skill](https://github.com/martian56/raven-language-skill)
- **License:** MIT
- **Homepage:** https://raven.ufazien.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.