Bbetlang

Syntax

Operators, literals, comments, and how statements end.

The shape of bet source: operators, literals, comments, and where a statement decides it’s done. Keyword meanings live in Keywords; type spellings in Types.

Operators

Conventional C-family operators. The keywords get to be silly; the punctuation does not.

  • Arithmetic: + - * / %
  • Comparison: == != < <= > >=
  • Logical: && || !
  • Bitwise: & | ^ ~ << >>
  • Assignment: = and compound += -= *= /= %= &= |= ^= <<= >>=
  • Structural: -> . , : [ ] ( ) { }

Longest match wins, so <<= beats << beats <.

Precedence

Lowest to highest:

||  <  &&  <  comparisons  <  |  <  ^  <  &  <  (<< >>)  <  (+ -)  <  (* / %)
    <  as  <  unary(! ~ -)  <  postfix(. call [])  <  primary

One deliberate break from C: the bitwise operators & ^ | bind tighter than the comparisons (Go’s rule). So flags & MASK == 0 parses as (flags & MASK) == 0, which retires one of C’s most beloved footguns before it can go off.

Literals

  • Integers: decimal 42, hex 0x40, binary 0b1010, with _ digit separators (1_000).
  • Floats: 3.5, 3e8, with exponents.
  • Strings: "...", UTF-8, type str. Escapes: \n \t \r \\ \" \' \0 \xHH.
  • Byte char: 'A' gives a u8.
  • Booleans: nocap / cap. Nil: ghosted.
lowkey n = 1_000        // 1000
lowkey hex = 0xFF       // 255
lowkey pi = 3.14
lowkey c: u8 = 'A'      // 65

Comments

  • Line: // runs to the end of the line.
  • Block: /* ... */, which does not nest.

Statement termination

Newlines carry weight here. A newline ends the current statement when the line’s last token could plausibly end one: an identifier, a literal, a closing bracket ) ] }, or a statement keyword (bet, dip, skip, bounce). If the line trails off on an operator, ,, ., ->, an assignment op, or an open bracket, the statement keeps going onto the next line. You can write an explicit ;, nobody will stop you, but it isn’t idiomatic and the formatter deletes it on sight.

Gotcha (Go’s rule): a bare struct literal can’t be the unparenthesized header of fr, vibin, squad, or vibe, because Ident { is ambiguous with the block that follows. Wrap it in parens when you need it.

Expression forms

  • Postfix: field access x.f, method call x.m[T](args), indexing x[i], and the unchecked deref tag.trust() in crib.
  • Allocation: cop <init> in <crib>, where <init> is a struct literal or a moods-variant constructor.
  • Struct literal: Name{ field: expr, ... } (trailing comma ok).
  • Array or slice literal: [10, 20, 30]; an empty [] needs a type annotation (lowkey xs: []int = []).
  • Call args may carry optional labels, used for the allocator context: stash.new(in: crib).
  • Cast: expr as Type.