Syntax
Jiang syntax is organized around declarations, explicit types, and visible low-level operations. When reading a file, start with imports and top-level declarations, then move into statements and expressions inside function bodies.
Naming Style
Section titled “Naming Style”The project uses these conventions:
- Type names use
PascalCase. - Function names, variable names, field names, enum members, and module aliases use
snake_case. - Primitive types such as
Int,Bool, andUInt8are written like ordinary type names.
enum TokenKind { kw, string_lit, left_paren,}
struct SourceFile { UInt8[]& file_path; Int start_offset;}
UInt8[]& read_source(UInt8[]& file_path) { return file_path;}Self is a special name in type position. self is available in instance methods and init bodies; functions without a self parameter do not have self.
Source Files
Section titled “Source Files”A source file is a sequence of top-level items:
importaliasconst- global declarations
- functions
struct,enum,union,traitextendcomptimeblocks
import math = "utils/math.jiang";
alias Byte = UInt8;alias answer = math.answer;
public const Int default_limit = 1024;
public struct Pair { Int left; Int right;}
public Int add(Int left, Int right) { return left + right;}public marks a declaration as visible outside the module.
public const exports a compile-time value through the module interface. comptime { ... } is a
top-level compile-time block for source selection; see Const and Comptime.
Keyword Options
Section titled “Keyword Options”Some keywords can carry options. Jiang writes these options with square brackets after the keyword:
enum [UInt8] ByteTag { block = 1, item,}The old keyword(...) form is not used for keyword options. Parentheses remain ordinary expression
or type syntax, so keyword options stay visually separate from function calls.
Statements
Section titled “Statements”Blocks contain declarations, destructuring statements, assignments, call statements, control-flow statements, and defer.
Int main() { Int total! = 0;
for i in 0..10 { total = total + i; }
return total;}Most statements end with semicolons. Control-flow forms that own a block, such as if, switch, while, and for, do not need an extra semicolon after the block.
Blocks
Section titled “Blocks”A block has a value only when it ends with a tail expression without a semicolon:
Int value = { Int base = 40; base + 2}Without a tail expression, the block value is ().
Expressions
Section titled “Expressions”Jiang expressions include literals, names, calls, field access, indexing, slicing, arithmetic, comparisons, if, switch, try catch, and blocks.
Int value = if flag { 1} else { 2}Field literals are written with their type path:
Point origin = Point(x: 0, y: 0)Implicit Operation Layer
Section titled “Implicit Operation Layer”$ enters the implicit operation layer for a value or type:
Int value = 42;Int& ref = value$.ref();Int copied = ref$.get();
UInt size = Int$.size();Use parentheses when applying $ to a compound expression:
Int raw = (left + right)$.as(Int);Prefer safe target-type initialization such as Float(value) for ordinary conversions. Do not use
value$.as(Type) as the everyday conversion spelling; it is a low-level cast form for raw pointers,
integer addresses, FFI, and similar code.
Patterns
Section titled “Patterns”is performs pattern matching. Optional values use .some(...):
if maybe is .some(value) { return value;} else { return 0;}Mutable payload bindings write the payload type explicitly:
if maybe is .some(Int value!) { value = value + 1;}switch uses the same style of patterns for optional, variant, and literal matches.