Skip to content

Latest commit

 

History

History
173 lines (128 loc) · 6.2 KB

File metadata and controls

173 lines (128 loc) · 6.2 KB

Operators

Casa uses postfix (reverse Polish) notation. Operands are pushed onto the stack first, then the operator consumes them and pushes the result. There is no operator precedence.

Stack-Based Evaluation

In most languages you write (3 + 4) * 2. In Casa, you write 3 4 + 2 *. Here is how it evaluates step by step:

Step       Operation    Stack (top on right)
────       ─────────    ────────────────────
           start        [ ]
3          push 3       [ 3 ]
4          push 4       [ 3, 4 ]
+          add          [ 7 ]
2          push 2       [ 7, 2 ]
*          multiply     [ 14 ]

The stack replaces parentheses and precedence rules. Values are consumed left to right, and every operator immediately uses the top values on the stack.

Operand order

Arithmetic and comparison operators use different stack conventions:

  • Arithmetic (+ - * / % << >> & | ^): a b op = a op b. The value pushed first is the left operand. This means 10 3 - is 10 - 3 = 7 — natural left-to-right reading.
  • Comparison (== != < <= > >=): a b op = b op a. The top of the stack is the left operand, matching function call convention. This means 0 1 > is 1 > 0 = true.
10 3 -     # 10 - 3 = 7   (arithmetic: left-to-right)
10 3 >     # 3 > 10 = false (comparison: top is left operand)

Arithmetic

All arithmetic operators consume two values and produce one.

Operator Stack Effect Description
+ a int -> a Addition. The second operand must be int; result type matches the first operand. Works on ptr for pointer arithmetic.
- a int -> a Subtraction. Same typing rules as +.
* int int -> int Multiplication
/ int int -> int Integer division (truncates toward zero)
% int int -> int Modulo (remainder)
34 35 + print    # 69
1357 20 - print  # 1337
7 6 * print      # 42
14 3 / print     # 4
14 3 % print     # 2

Pointer Arithmetic

+ and - support ptr as the first operand, allowing offset-based heap access:

32 alloc = buf
42 buf (ptr) 8 + store64    # store 42 at byte offset 8
buf (ptr) 8 + load64 print  # 42

Bitshift

Operator Stack Effect Description
<< a int -> a Left shift. Result type matches the first operand.
>> a int -> a Right shift. Result type matches the first operand.
1 4 << print    # 16
16 4 >> print   # 1

Bitwise

Operator Stack Effect Description
& int int -> int Bitwise AND
| int int -> int Bitwise OR
^ int int -> int Bitwise XOR
~ int -> int Bitwise NOT (one's complement)
12 10 & print   # 8 (1100 AND 1010 = 1000)
12 10 | print   # 14 (1100 OR 1010 = 1110)
12 10 ^ print   # 6 (1100 XOR 1010 = 0110)
12 ~ print      # -13 (inverts all bits)

Note: & is also used as a function reference prefix (&name). When followed by an identifier, it creates a function reference. When used after two values on the stack, it performs bitwise AND.

Comparison

All comparison operators consume two values of the same type and push a bool. Equality operators require the operand type to satisfy the Eq trait; ordering operators require Ord.

Operator Stack Effect Description
== [T: Eq] T T -> bool Equal
!= [T: Eq] T T -> bool Not equal
< [T: Ord] T T -> bool Less than
<= [T: Ord] T T -> bool Less than or equal
> [T: Ord] T T -> bool Greater than
>= [T: Ord] T T -> bool Greater than or equal

Built-in primitives (int, bool, char, cstr, ptr) and enums get direct bytecode comparison. User-defined types must provide impl T { fn eq ... } (and fn lt ... for ordering); the operator then lowers to the corresponding trait method call. See traits.md for Eq and Ord.

1 1 == print    # true
1 0 != print    # true
0 1 > print     # true (1 > 0, top is left operand)
1 0 > print     # false (0 > 1)

Comparison operators use the top of the stack as the left operand (a b op = b op a). See Operand order above.

String comparison

String == and != compare by content (byte-by-byte), not by pointer identity. Other comparison operators (<, <=, >, >=) are not supported for strings.

"hello" "hello" == print    # true
"hello" "world" != print    # true

Boolean

Operator Stack Effect Description
&& bool bool -> bool Logical AND
|| bool bool -> bool Logical OR
! bool -> bool Logical NOT
true true && print    # true
true false || print   # true
true ! print          # false

Assignment

Assignment operators pop a value from the stack and store it in a named variable.

Operator Stack Effect Description
= name T -> None Assign top of stack to variable name
= name:type T -> None Assign with type annotation, verifies and narrows the type
+= name int -> None Add top of stack to variable name
-= name int -> None Subtract top of stack from variable name
42 = count        # count is now 42
1 += count        # count is now 43
10 -= count       # count is now 33

Type annotations

The = name:type form lets you annotate the type of a variable at assignment time. The type checker verifies the stack value is compatible and uses the annotated type for the variable.

42 = x:int                  # explicit int annotation
Option::None = empty:Option[int]    # narrow bare Option to Option[int]

Variables are created on first assignment. See Functions and Lambdas -- Variables for scoping rules.

See Also