ArchLang Playground

Relational (right-of) — an ArchLang floor plan example

Rooms positioned relative to one another with right-of, below and align, resolved to coordinates by arithmetic.

This plan compiles to 4 rooms, 60 m² of floor area and 2 windows.

Living 20.0 m² Kitchen 12.0 m² Bedroom 17.5 m² Bath 10.5 m² 8200 N 02 m PROJECTRelational Layout DemoDRAWN BYArchCanvasDATE2026-06-26SCALE1:100
"Relational 1BR" — a 4-room floor plan, 60 m² total: Living (20 m²), Kitchen (12 m²), Bedroom (17.5 m²), Bath (10.5 m²); 1 door, 2 windows, entrance via door_1.
Open in the editor

The source

This is the whole plan. The drawing above is what the compiler produced from it — nothing was drawn by hand.

# Relational placement (v1.0): rooms positioned relative to one another with
# `right-of` / `left-of` / `below` / `above` (+ `align` and `gap`), resolved to
# absolute coordinates by pure arithmetic in dependency order. Only `living` is
# anchored with `at`; every other room derives its position from a neighbour, so
# changing the anchor or a size reflows the whole plan deterministically.
#
# FOUR DELIBERATE WARNINGS, and all four are one fact about the language:
#
#   W_ROOM_DISCONNECTED x3 (Kitchen, Bedroom, Bath) + W_ROOM_NOT_ENCLOSED x1 (Bath)
#
# A relationally-laid plan cannot carry partitions that reflow with it. Rooms resolve to
# coordinates, but nothing can read a resolved room boundary back OUT: a wall point is an
# expression, expressions see `let` constants and the nine built-ins, and there is no
# `kitchen.x` — writing one is `E_UNKNOWN_REF`, not a coordinate. So the four interior
# boundaries here (living|kitchen, living|bedroom, kitchen|bath, bedroom|bath) carry no
# wall, no wall is there to host a door, and three of the four rooms have no way in.
#
# Both obvious repairs were measured, and both cost more than they buy:
#
#   * A cased `opening` on a wall-free boundary clears W_ROOM_DISCONNECTED from
#     `arch lint` and raises W_OPENING_OFF_WALL from `arch validate` — `lint` is the
#     soundness layer alone, `validate` is parse + resolve + lint. That is one warning
#     traded for another, and the second one is the true one.
#   * Absolute partitions at x=5000 and y=4000 would compile clean and would make this
#     file a plan whose ROOMS reflow and whose WALLS silently do not — the trap the file
#     exists to warn about. Hoisting every dimension into `let` constants and writing the
#     walls as arithmetic over them fixes the *size* case only: change `bath right-of bed`
#     to `bath below kitchen` and the walls stay exactly where they were. It also rebuilds
#     by hand the coordinate model `right-of` exists to remove.
#
# So these four stand. `arch validate` is clean; `arch validate --strict` reports them.
# Everything NOT caused by that limitation was repaired rather than documented: the
# kitchen and the bath have their serviced fixtures, and the bedroom has a window.
plan "Relational 1BR" {
  units mm
  grid 50
  scale 1:100
  north up

  # Exterior shell (walls are always absolute — relational placement is rooms-only).
  wall exterior thickness 200 { (0,0) (8000,0) (8000,7500) (0,7500) close }

  room id=living  at (0,0)                         size 5000x4000 label "Living"
  room id=kitchen right-of living align top  gap 0 size 3000x4000 label "Kitchen"
  room id=bed     below living    align left gap 0 size 5000x3500 label "Bedroom"
  room id=bath    right-of bed    align top  gap 0 size 3000x3500 label "Bath"

  door   at (1000,0) width 1000 wall exterior hinge left swing in
  window at (6500,0) width 1800 wall exterior
  window at (3200,7500) width 1600 wall exterior

  # Head against the south wall — the only edge of this room the bed's 1500 mm head can
  # back onto, since the boundary it shares with the living room carries no wall.
  furniture bed at (300,5400) size 1500x2000 label "Bed" rotate 180

  # A handful of freestanding pieces in the two upper rooms — this file's only wall is
  # the exterior shell (relational placement is rooms-only, so there are no partitions
  # to write `against wall` on), so everything below is a plain `at`.
  furniture sofa         at (200,2900) size 1800x800 label "Sofa" in living
  furniture coffee_table at (200,2000) size 900x500               in living
  furniture dining_table at (5300,300)  size 2400x1200 label "Table" in kitchen
  furniture chair        at (5600,1700) size 450x450               in kitchen
  furniture chair        at (6800,1700) size 450x450               in kitchen

  # The serviced pieces. Every one of these is `requiresWall` — a sink, a stove, a WC and
  # a basin are plumbed or vented, so each backs onto the only wall this plan has, the
  # exterior shell. That is also why the kitchen run and the bathroom run both sit on the
  # EAST facade: the boundaries these two rooms share with their neighbours carry no wall
  # to back onto (see the note in the header).
  furniture sink   at (7300,2400) size 600x800 rotate 90 in kitchen
  furniture stove  at (7300,3300) size 600x600 rotate 90 in kitchen

  furniture wc     at (7200,4300) size 700x400 rotate 90 in bath
  furniture basin  at (7450,5000) size 450x600 rotate 90 in bath
  furniture shower at (5200,6500) size 900x900            in bath

  # Overall width, outside face to outside face (`faces` projects each endpoint onto
  # the wall it runs into, so it prints the true 8200 rather than the 8000 room grid).
  dim faces (0,7500)->(8000,7500) offset 600

  title {
    project "Relational Layout Demo"
    drawn_by "ArchCanvas"
    date "2026-06-26"
  }
}

Read more