Appendix B: Operators and Symbols

This appendix is a complete reference for every operator and special symbol in VibeLang, including precedence rules, descriptions, and examples.


B.1 Operator Precedence Table

Operators listed from highest precedence (binds tightest) to lowest. All binary operators are left-associative unless noted.

PrecedenceOperator(s)NameAssociativity
1.Member accessLeft
2() []Call / IndexLeft
3?Error propagationPostfix
4! - (unary)Logical NOT / NegationPrefix
5* / %Multiply / Divide / ModLeft
6+ -Add / SubtractLeft
7..RangeNone
8< > <= >=ComparisonLeft
9== !=EqualityLeft
10&&Logical ANDLeft
11||Logical ORLeft
12|>PipeLeft
13:= =Binding / AssignmentRight

When in doubt, use parentheses.


B.2 Arithmetic Operators

+ — Addition

Adds two numeric values. Also concatenates strings.

VibeLang
sum := 3 + 4            // 7
greeting := "hi" + "!"  // "hi!"

- — Subtraction / Negation

Binary subtraction or unary negation.

VibeLang
diff := 10 - 3   // 7
neg := -42        // -42

* — Multiplication

VibeLang
area := width * height

/ — Division

Integer division truncates toward zero. Division by zero is a runtime error.

VibeLang
half := 10 / 2      // 5
truncated := 7 / 3  // 2

% — Remainder

Returns the remainder of integer division. Result sign matches the dividend.

VibeLang
remainder := 17 % 5   // 2
is_even := n % 2 == 0

B.3 Comparison Operators

All comparison operators return Bool.

== / != — Equality

VibeLang
if status == 200 { println("OK") }
if name != "" { println(name) }

< / > / <= / >= — Ordering

VibeLang
if temperature < 0 { println("freezing") }
if score > high_score { high_score = score }
if retries <= MAX_RETRIES { attempt(request) }
if age >= 18 { println("eligible") }

B.4 Logical Operators

Logical operators work exclusively on Bool values. && and || short-circuit.

&& — Logical AND

Returns true only if both operands are true.

VibeLang
if is_valid && is_authorized { proceed() }

|| — Logical OR

Returns true if either operand is true.

VibeLang
if is_admin || is_owner { grant_access() }

! — Logical NOT

Unary prefix. Returns the boolean inverse.

VibeLang
if !found { println("not found") }

B.5 Assignment Operators

:= — Binding

Creates a new variable binding (immutable by default, mutable with mut).

VibeLang
name := "VibeLang"
mut counter := 0

= — Assignment

Reassigns a value to an existing mutable binding.

VibeLang
mut x := 10
x = 20

Using = on an immutable binding is a compile-time error.


B.6 Pipe Operator

|> — Pipe

Passes the left expression as the first argument to the function on the right. Enables readable left-to-right data transformation chains.

VibeLang
result := raw_input
  |> trim()
  |> parse_int()
  |> validate()

Equivalent without pipe: validate(parse_int(trim(raw_input))).


B.7 Range Operator

.. — Range

Creates a half-open range (start inclusive, end exclusive). Used in for loops and slice operations.

VibeLang
for i in 0..5 {
  println(i.to_str())  // 0, 1, 2, 3, 4
}

B.8 Error Propagation Operator

? — Propagate

Postfix on Result<T, E>. If the result is an error, the function returns it immediately. If success, the inner value is extracted.

VibeLang
pub read_config(path: Str) -> Result<Config, Error> {
  @effect io
  text := fs.read_text(path)?
  json.parse(text)?
}

Only valid inside functions that return Result<T, E>.


B.9 Special Symbols

-> — Return Type Arrow

Separates a function's parameter list from its return type.

VibeLang
pub add(a: Int, b: Int) -> Int { a + b }

=> — Match Arm

Separates a pattern from its body in match and select branches.

VibeLang
match direction {
  "north" => move(0, 1)
  "south" => move(0, -1)
  _ => stay()
}

: — Type Annotation

Separates a name from its type in declarations, parameters, and struct fields.

VibeLang
pub type Config { host: Str, port: Int }

, — Separator

Separates items in arguments, list literals, map entries, and type parameters.

VibeLang
result := add(3, 4)
items := [1, 2, 3]

. — Member Access

Accesses a field or method on a value.

VibeLang
length := name.len()

@ — Annotation Prefix

Introduces a contract annotation: @intent, @examples, @require, @ensure, or @effect.

VibeLang
pub clamp(val: Int, lo: Int, hi: Int) -> Int {
  @intent "constrain val to [lo, hi]"
  @require lo <= hi
  @ensure . >= lo && . <= hi
  if val < lo { lo } else if val > hi { hi } else { val }
}

// — Line Comment

Everything after // on a line is ignored by the compiler.

{ } — Block Delimiters

Enclose function bodies, control flow branches, type definitions, and match arms.

( ) — Grouping / Call

Group sub-expressions or delimit function parameters and call arguments.

[ ] — List / Index

Create list literals or index into a list.

VibeLang
items := [10, 20, 30]
first := items[0]

B.10 Annotation Keywords

AnnotationPurposeChapter
@intentNatural-language description of behavior6
@examplesInput/output examples for verification6
@requirePrecondition that callers must satisfy6
@ensurePostcondition the function guarantees6
@effectSide effect declaration7

B.11 Quick Reference Card

SymbolNameExample
+Add / Concatenatea + b
-Subtract / Negatea - b, -x
*Multiplya * b
/Dividea / b
%Remaindera % b
==Equala == b
!=Not equala != b
<Less thana < b
>Greater thana > b
<=Less or equala <= b
>=Greater or equala >= b
&&Logical ANDa && b
||Logical ORa || b
!Logical NOT!a
:=Bindingx := 5
=Assignmentx = 10
|>Pipex |> f()
..Range0..10
?Error propagationresult?
->Return typefn() -> Int
=>Match armx => body
:Type annotationx: Int
.Member accessobj.field
@Annotation prefix@intent "..."
//Comment// note