Operators in BLISS
Learn arithmetic, comparison, bitwise, shift, and assignment operators in BLISS, including keyword operators and the distinctive dot dereference
Operators in BLISS reflect the language’s systems programming heritage and its typeless, expression-oriented design. Because every BLISS construct is an expression that produces a fullword value, operators combine freely to build larger expressions — including the value of an IF or a block.
BLISS makes two design choices that set its operators apart from C-family languages. First, comparisons use keyword operators (GTR, LSS, EQL, …) instead of symbols, leaving > and < available for other purposes (and avoiding ambiguity in the parser). Second, variable names evaluate to addresses, not values, so the unary dot (.) is effectively the most-used operator in any real BLISS program.
This tutorial walks through arithmetic, comparison, bitwise, shift, and assignment operators using a single program. Output is bridged to printf through a small C wrapper, the same pattern introduced in the Hello World tutorial.
The Operator Categories
| Category | Operators | Notes |
|---|---|---|
| Arithmetic | + - * / MOD | Integer arithmetic on machine words |
| Comparison (signed) | EQL NEQ GTR LSS GEQ LEQ | Yield 1 (true) or 0 (false) |
| Comparison (unsigned) | EQLU NEQU GTRU LSSU GEQU LEQU | Treat operands as unsigned |
| Bitwise logical | AND OR NOT XOR EQV | Bit-by-bit on the full machine word |
| Shift | ^ | Positive count shifts left; negative shifts right |
| Assignment | = | An expression that returns the assigned value |
| Dereference | . (unary prefix) | Fetches the contents at an address |
A few things worth noting:
NOTis bitwise, not boolean —NOT 0is-1(all bits set), not1. BLISS treats a value as true when its low bit is1, soNOTstill inverts truthiness in conditional context.MODis a keyword like the comparison operators, not a%symbol.- There are no compound assignment operators like
+=or*=in BLISS — writex = .x + 1instead.
The Program
This single BLISS module exercises each operator category and hands the results to C wrapper routines that print them. Each routine prints one labeled line of output.
Create a file named operators.bli:
MODULE operators =
BEGIN
EXTERNAL ROUTINE
print_arith,
print_comp,
print_logic,
print_shift,
print_prec,
print_assign,
print_dot;
GLOBAL ROUTINE run_operators : NOVALUE =
BEGIN
LOCAL a, b, x, y;
a = 10;
b = 3;
! Arithmetic: + - * / MOD all work on full machine words
print_arith(.a + .b, .a - .b, .a * .b, .a / .b, .a MOD .b);
! Comparison: keyword operators yielding 1 (true) or 0 (false)
print_comp(.a EQL .b, .a NEQ .b, .a GTR .b, .a LSS .b);
! Bitwise logical: AND OR XOR operate on every bit of the word
print_logic(12 AND 10, 12 OR 10, 12 XOR 10);
! Shift: ^ takes a positive count for left shift, negative for right shift
print_shift(1 ^ 4, 64 ^ -2);
! Precedence: * binds tighter than +, parentheses force grouping
print_prec(2 + 3 * 4, (2 + 3) * 4);
! Assignment is itself an expression returning the assigned value
y = 100;
x = (y = .y + 5);
print_assign(.x, .y);
! The dot operator: bare name = address, .name = contents
a = 42;
b = .a + 1;
print_dot(.a, .b)
END;
END
ELUDOM
Create a file named wrapper.c:
| |
Walking Through the Operators
Arithmetic
+ - * / behave as expected on machine words, and integer division truncates toward zero. MOD is a keyword, so it sits between operands like any other binary operator: .a MOD .b. There is no exponentiation operator in core BLISS.
Comparison and the Truth Convention
Each comparison yields exactly 1 for true and 0 for false. In conditional context, however, BLISS does not insist on those exact values: any expression with a 1 in the low bit is treated as true. That is why NOT continues to invert truthiness even though it is a bitwise operator.
Unsigned variants (EQLU, GTRU, …) exist because BLISS is typeless — the compiler cannot guess whether .x was meant as signed or unsigned, so the operator carries the interpretation.
Bitwise Logic
AND, OR, XOR, EQV, and NOT operate bit-by-bit across the entire machine word. For 12 AND 10:
12 = ...0000 1100
10 = ...0000 1010
AND ...0000 1000 = 8
The Shift Operator
The single shift operator ^ reads as “shift by.” A positive right-hand side shifts left; a negative right-hand side shifts right. 1 ^ 4 shifts 1 left by four positions to produce 16. 64 ^ -2 shifts 64 right by two positions, also producing 16.
Precedence and Associativity
BLISS precedence runs roughly: dot (highest) → unary minus → * / MOD → + - → shift → comparison → NOT → AND → OR XOR EQV → assignment (lowest). Parentheses override grouping just as in C.
Assignment as an Expression
Since every BLISS construct returns a value, so does =. The statement x = (y = .y + 5) evaluates .y + 5, stores it into y, and the assignment expression yields the new value, which is then stored into x. Both end up with 105.
The Dot, Revisited
Without the dot, .a + 1 would attempt to add 1 to the address of a — a meaningful operation in BLISS, but rarely what you want for arithmetic. Reading b = .a + 1 aloud as “store into b the contents of a plus one” matches what the compiler does.
Running with Docker
| |
The two-step build mirrors the Hello World tutorial: blissc lowers BLISS to a native object file through LLVM, then gcc links it with the C wrapper containing main and the I/O bridge routines.
Expected Output
Arithmetic: 10+3=13, 10-3=7, 10*3=30, 10/3=3, 10 MOD 3=1
Comparison: 10 EQL 3=0, 10 NEQ 3=1, 10 GTR 3=1, 10 LSS 3=0
Bitwise: 12 AND 10=8, 12 OR 10=14, 12 XOR 10=6
Shift: 1 ^ 4 = 16, 64 ^ -2 = 16
Precedence: 2 + 3 * 4 = 14, (2 + 3) * 4 = 20
Assignment as expression: x = 105, y = 105
Dot operator: .a = 42, .b = .a + 1 = 43
Key Concepts
- Comparisons are keyword operators —
EQL,NEQ,GTR,LSS,GEQ,LEQfor signed values, plusEQLU/GTRU/… for unsigned interpretation. - Logical operators are bitwise —
AND,OR,XOR,EQV, andNOToperate on every bit; BLISS uses the low bit as its truth indicator in conditional context. - One shift operator handles both directions —
value ^ countshifts left for positivecountand right for negativecount. - No compound assignment — write
x = .x + 1; there is no+=or++in BLISS. - Assignment is an expression —
x = (y = expr)works because every construct, including=, produces a value. - The dot operator participates in expressions —
.a + .breads contents of two variables and adds them, whilea + bwould add their addresses. MODis a keyword, not a symbol — there is no%operator in BLISS.- Parentheses cost nothing — when in doubt about precedence, group explicitly; the optimizing compiler removes any redundancy.
Running Today
All examples can be run using Docker:
docker pull codearchaeology/bliss:latest
Comments
Loading comments...
Leave a Comment