Skip to content
kata / a language workbench

Syntax and values

KataScript files use the .ks extension. A program is a sequence of statements; semicolons are optional. Braces delimit function bodies and control-flow bodies.

# A line comment starts with a hash.
let answer = 6 * 7
print(answer)

Whitespace and newlines do not define indentation-based scopes. Use indentation to make the brace structure easy to read.

print(42) # Int: arbitrary precision
print(3.5) # Float: 64-bit floating point
print(0xff) # hexadecimal Int
print(0b1010) # binary Int
print(true)
print(nil)
print("hello")
print(b'hello\xff') # Bin: bytes
print((1, "one")) # a tuple

Int arithmetic is arbitrary precision. Float arithmetic is approximate. Integer division stays integer-valued: 5 / 2 evaluates to 2. Choose a floating-point operand when a fractional result is intended, and avoid using mixed numeric comparisons at extreme magnitudes as exact arithmetic.

You can inspect a value’s type:

print(typeof(42)) # Int
print(typeof("hello")) # Str
print(Int) # types themselves are values
PurposeOperators
Arithmetic+, -, *, /, %
Comparison==, !=, <, >, <=, >=
Unary-, !
Short-circuit logic&&, `

Multiplication, division, and remainder bind more tightly than addition and subtraction. Use parentheses when a grouping deserves emphasis. + also concatenates strings.

Logical operators evaluate their right-hand side only when needed. Falsy values include nil, false, numeric zero, the empty string, the empty tuple, and records with no fields. An empty array or map still has record fields and is truthy; test its length when you mean “has elements.”

if and with can produce values from their final expression:

let label = if 8 > 5 { "large" } else { "small" }
let area = with width = 6, height = 7 {
width * height
}
print("{label}: {area}")

with introduces a standalone scope, optionally with bindings. Bare braces do not introduce a standalone expression block. Map literal syntax is not implemented.

Next: bindings and scope.