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