Built-in Functions

Complete reference for all built-in functions in Chasm, math, vector, color, bitwise, strings, and I/O.

Built-in functions are available in every Chasm file without any import. They are implemented in the runtime (chasm_rt.h) and called directly from generated C code.

Math

These functions operate on float unless noted. Integer arguments are automatically widened.

FunctionReturnsDescription
abs(v)floatAbsolute value. abs(-3.5) → 3.5
sqrt(v)floatSquare root. sqrt(9.0) → 3.0
pow(b, e)floatb raised to the power e. pow(2.0, 10.0) → 1024.0
sin(v)floatSine of v in radians
cos(v)floatCosine of v in radians
tan(v)floatTangent of v in radians
atan2(y, x)floatAngle in radians from the origin to (x, y). Use instead of atan to handle all quadrants
floor(v)floatRound down to nearest integer. floor(3.7) → 3.0
ceil(v)floatRound up to nearest integer. ceil(3.2) → 4.0
round(v)floatRound to nearest integer. round(3.5) → 4.0
fract(v)floatFractional part. fract(3.7) → 0.7
sign(v)float-1.0 if negative, 0.0 if zero, 1.0 if positive
min(a, b)floatSmaller of two values
max(a, b)floatLarger of two values
clamp(v, lo, hi)floatRestrict v to the range [lo, hi]. clamp(150.0, 0.0, 100.0) → 100.0
wrap(v, lo, hi)floatWrap v into [lo, hi). Useful for looping angles
snap(v, step)floatRound v to the nearest multiple of step. snap(7.3, 4.0) → 8.0
scale(v, factor)floatMultiply v by factor. Useful with |>
lerp(a, b, t)floatLinear interpolation. lerp(0.0, 10.0, 0.3) → 3.0. t=0 returns a, t=1 returns b
smooth_step(a, b, t)floatHermite interpolation, starts and ends slowly, eases in the middle
smoother_step(a, b, t)float5th-order interpolation, even smoother than smooth_step
ping_pong(t, len)floatBounce t back and forth between 0 and len. Useful for pulsing effects
move_toward(cur, target, step)floatMove cur toward target by at most step. Never overshoots
angle_diff(a, b)floatShortest signed angle difference between two angles in radians. Handles wrap-around
deg_to_rad(d)floatConvert degrees to radians. deg_to_rad(180.0) → 3.14159...
rad_to_deg(r)floatConvert radians to degrees

Common patterns

# Clamp player position to screen
@player_x = clamp(@player_x + dx * dt, 0.0, screen_w - player_w)

# Smooth follow camera
@cam_x = lerp(@cam_x, @target_x, 5.0 * dt)

# Rotate smoothly toward target angle
@angle = @angle + angle_diff(@angle, @target_angle) * 8.0 * dt

# Pulsing scale effect
scale = 1.0 + sin(@time * 4.0) * 0.05

Vector Math

2D vector operations, all take component pairs rather than a struct type:

FunctionReturnsDescription
vec2_len(x, y)floatLength (magnitude) of vector (x, y)
vec2_dot(ax, ay, bx, by)floatDot product. Positive means same direction, negative means opposite
vec2_dist(ax, ay, bx, by)floatDistance between points (ax, ay) and (bx, by)
vec2_angle(x, y)floatAngle of vector in radians. vec2_angle(1.0, 0.0) → 0.0
vec2_cross(ax, ay, bx, by)float2D cross product (scalar). Sign tells you which side of the line
vec2_norm_x(x, y)floatX component of the normalized (unit length) vector
vec2_norm_y(x, y)floatY component of the normalized (unit length) vector
# Move entity toward target at constant speed
dx = target_x - @enemy_x
dy = target_y - @enemy_y
dist = vec2_len(dx, dy)
if dist > 0.0 do
  @enemy_x = @enemy_x + vec2_norm_x(dx, dy) * speed * dt
  @enemy_y = @enemy_y + vec2_norm_y(dx, dy) * speed * dt
end

Type Conversion

FunctionReturnsDescription
to_int(v)intFloat → int. Truncates toward zero. to_int(3.9) → 3
to_float(v)floatInt → float. to_float(7) → 7.0
to_bool(v)boolInt → bool. 0 is false, anything else is true

Chasm never implicitly converts between int and float. If the compiler gives you a type mismatch, one of these is the fix.

Color

Colors in Chasm are packed 32-bit integers in 0xRRGGBBAA format, red, green, blue, alpha, each 0–255.

FunctionReturnsDescription
rgb(r, g, b)intPack RGB into 0xRRGGBBFF (fully opaque)
rgba(r, g, b, a)intPack RGBA into 0xRRGGBBAA
color_r(c)intExtract red channel (0–255)
color_g(c)intExtract green channel (0–255)
color_b(c)intExtract blue channel (0–255)
color_a(c)intExtract alpha channel (0–255)
color_lerp(a, b, t)intInterpolate between two packed colors. t=0 returns a, t=1 returns b
color_mix(a, b, t)intAlias for color_lerp
red   = rgb(255, 0, 0)          # 0xff0000ff
semi  = rgba(255, 0, 0, 128)    # 50% transparent red
flash = color_lerp(red, 0xffffffff, @flash_t)

Bitwise

All bitwise functions operate on int:

FunctionReturnsDescription
bit_and(a, b)intBitwise AND. bit_and(0b1010, 0b1100) → 0b1000
bit_or(a, b)intBitwise OR
bit_xor(a, b)intBitwise XOR. Toggle bits
bit_not(v)intBitwise NOT (complement)
bit_shl(v, n)intShift v left by n bits, multiply by 2ⁿ
bit_shr(v, n)intShift v right by n bits, divide by 2ⁿ
# Check a flag
flags = 0b00001101
if bit_and(flags, 0b0100) != 0 do
  print("flag 2 is set")
end

# Set a flag
flags = bit_or(flags, 0b0010)

# Clear a flag
flags = bit_and(flags, bit_not(0b0100))

String Conversion

FunctionReturnsDescription
int_to_str(v)stringInteger to decimal string. int_to_str(42) → "42"
float_to_str(v)stringFloat to string. float_to_str(3.14) → "3.14"
bool_to_str(v)stringBool to string. bool_to_str(true) → "true"
str_from_char(c)stringByte value to 1-character string. str_from_char(65) → "A"

String interpolation "#{x}" calls these automatically, so explicit calls are rarely needed.

I/O and Debug

FunctionDescription
print(x)Print x followed by a newline. Works on int, float, bool, string
log(x)Alias for print
assert(cond)Abort the process if cond is false. Use for invariants
todo()Mark a code path as not yet implemented, aborts with a message
defp get_tier(score :: int) :: string do
  if score < 0 do
    assert(false)   # score cannot be negative
  end
  if score < 100 do return "bronze" end
  if score < 500 do return "silver" end
  return "gold"
end

File I/O

FunctionReturnsDescription
file_read(path)stringRead entire file contents into the persistent arena
file_write(path, content)Overwrite file with string
file_exists(path)boolCheck whether a file exists at path

file_read allocates into the persistent arena, the result is valid for the life of the process. Use it in on_init for config files, level data, and other assets:

@level_data :: persistent = ""

def on_init() do
  if file_exists("levels/1.json") do
    @level_data = file_read("levels/1.json")
  end
end