# Cordial Language Reference Cordial is the primary source language for the Cord geometry system. It compiles to a trigonometric intermediate representation (TrigGraph) which can be evaluated as an f64 reference, compiled to WGSL shaders for GPU raymarching, or lowered to pure CORDIC shift-and-add arithmetic. File extension: `.crd` --- ## Variables ``` let r = 5 let height = 2 * pi let s: Obj = sphere(r) ``` - `let` introduces a new variable. - `: Obj` type annotation marks a variable as a renderable 3D object. - Variables can be reassigned: `r = 10` (no `let` on reassignment). --- ## Constants | Name | Value | |-----------|---------------| | `pi`, `PI`| 3.14159... | | `e`, `E` | 2.71828... | | `x` | Input X coord | | `y` | Input Y coord | | `z` | Input Z coord | | `reg` | NaN register | `x`, `y`, `z` are the spatial coordinates — use them to build mathematical expressions and SDF fields directly. --- ## Arithmetic | Syntax | Operation | |---------|----------------| | `a + b` | Addition | | `a - b` | Subtraction | | `a * b` | Multiplication | | `a / b` | Division | | `a ^ b` | Power (²,³ optimized) | | `-a` | Negation | Precedence: unary > power > multiplicative > additive. Parentheses for grouping: `(a + b) * c`. --- ## Comments ``` // line comment /= also a line comment /* block comment */ /* nested /* block */ comments */ ``` --- ## Trig Functions | Function | Aliases | Description | |----------|---------|-------------| | `sin(x)` | | Sine | | `cos(x)` | | Cosine | | `tan(x)` | | Tangent | | `asin(x)` | `arcsin` | Inverse sine | | `acos(x)` | `arccos`, `arcos` | Inverse cosine | | `atan(x)` | `arctan` | Inverse tangent | | `sinh(x)` | | Hyperbolic sine | | `cosh(x)` | | Hyperbolic cosine | | `tanh(x)` | | Hyperbolic tangent | | `asinh(x)` | `arcsinh` | Inverse hyperbolic sine | | `acosh(x)` | `arccosh`, `arcosh` | Inverse hyperbolic cosine | | `atanh(x)` | `arctanh` | Inverse hyperbolic tangent | --- ## Math Functions | Function | Aliases | Description | |----------|---------|-------------| | `sqrt(x)` | | Square root | | `exp(x)` | | e^x | | `ln(x)` | `log` | Natural logarithm | | `abs(x)` | | Absolute value | | `hypot(a, b)` | | √(a² + b²) | | `atan2(y, x)` | | Two-argument arctangent | | `min(a, b)` | | Minimum | | `max(a, b)` | | Maximum | | `length(a, b)` | `mag` | Magnitude (2D or 3D) | | `mix(a, b, t)` | `lerp` | Linear interpolation | | `clip(x, lo, hi)` | `clamp` | Clamp to range | | `smoothstep(e0, e1, x)` | | Hermite interpolation | | `quantize(x, step)` | | Snap to grid | --- ## SDF Primitives These construct signed distance fields centered at the origin. All dimensions are half-extents (centered geometry). | Function | Arguments | Description | |----------|-----------|-------------| | `sphere(r)` | radius | Sphere | | `box(hx, hy, hz)` | half-extents | Axis-aligned box | | `cylinder(r, h)` | radius, half-height | Z-axis cylinder | | `ngon(n, side)` | sides (≥3), side length | Regular polygon prism | | `N-gon(side)` | side length | Shorthand: `6-gon(2)` = hexagonal prism | --- ## Transforms Transforms take an SDF as the first argument and modify its coordinate space. | Function | Aliases | Arguments | Description | |----------|---------|-----------|-------------| | `translate(sdf, tx, ty, tz)` | `mov`, `move` | SDF + offsets | Translate | | `rotate_x(sdf, angle)` | `rx` | SDF + radians | Rotate around X | | `rotate_y(sdf, angle)` | `ry` | SDF + radians | Rotate around Y | | `rotate_z(sdf, angle)` | `rz` | SDF + radians | Rotate around Z | | `scale(sdf, factor)` | | SDF + uniform scale | Uniform scale | | `mirror_x(sdf)` | `mx` | SDF | Mirror across YZ plane | | `mirror_y(sdf)` | `my` | SDF | Mirror across XZ plane | | `mirror_z(sdf)` | `mz` | SDF | Mirror across XY plane | --- ## CSG Boolean Operations | Function | Aliases | Arguments | Description | |----------|---------|-----------|-------------| | `union(a, b)` | | two SDFs | Union (min) | | `intersect(a, b)` | | two SDFs | Intersection (max) | | `diff(a, b)` | `subtract` | two SDFs | Difference (max(a, -b)) | --- ## Waveform Functions | Function | Arguments | Description | |----------|-----------|-------------| | `saw(x)` | input | Sawtooth wave | | `tri(x)` | input | Triangle wave | | `square(x)` | input | Square wave | --- ## DSP / Signal Functions | Function | Arguments | Description | |----------|-----------|-------------| | `am(signal, carrier, depth)` | | Amplitude modulation | | `fm(signal, carrier, index)` | | Frequency modulation | | `lpf(signal, cutoff)` | | Low-pass filter approximation | | `hpf(signal, cutoff)` | | High-pass filter approximation | | `bpf(signal, lo, hi)` | | Band-pass filter approximation | | `dft(signal, n)` | | Discrete Fourier approximation | | `hilbert(x)` | `envelope` | Analytic signal envelope | | `phase(x)` | | Instantaneous phase | --- ## User-Defined Functions ``` f(a, b) = a^2 + b^2 let result = f(3, 4) ``` Define with `name(params) = body`. Body extends to the next newline or semicolon. Functions are expanded inline at each call site. --- ## Schematics (`sch`) Schematics are parameterized multi-statement blocks — like functions but with full block bodies containing `let` bindings, intermediate variables, and arbitrary nesting. The last expression is the return value. ``` sch Bracket(w, h, t) { let plate: Obj = box(w, h, t) let rib: Obj = box(t, h/2, t) union(plate, translate(rib, w/2, 0, 0)) } let b = Bracket(10, 5, 0.5) cast(b) ``` Schematics can call other schematics and user-defined functions. They can contain any number of statements. ``` sch Peg(r, h) { let shaft = cylinder(r, h) let head = translate(sphere(r * 1.5), 0, 0, h) union(shaft, head) } sch PegRow(n, spacing) { map(i, 0..n) { translate(Peg(0.5, 3), i * spacing, 0, 0) } } ``` --- ## Iteration (`map`) `map` evaluates a body for each integer in a range and unions all results. Iteration is unrolled at parse time — the TrigGraph is a DAG with no runtime loops. ``` map(variable, start..end) { body } ``` - `variable` — bound to each integer in `[start, end)` - `start..end` — exclusive range; bounds must resolve to constants - `body` — any expression or block; can reference the iteration variable - All iterations are unioned (min) - Max 1024 iterations ### Examples ``` // Row of 5 spheres along X let row = map(i, 0..5) { translate(sphere(1), i * 3, 0, 0) } // Ring of 8 spheres let ring = map(i, 0..8) { rotate_z(translate(sphere(0.5), 5, 0, 0), i * pi/4) } // Grid using nested maps inside a schematic sch Grid(nx, ny, spacing) { map(i, 0..nx) { map(j, 0..ny) { translate(sphere(0.4), i * spacing, j * spacing, 0) } } } let g = Grid(4, 6, 2) cast() ``` Since `map` is an expression, it works anywhere: inside `let` bindings, as arguments to functions, inside schematic bodies, or nested in other maps. --- ## Rendering with `cast()` Nothing renders without an explicit `cast()` call. | Syntax | Effect | |--------|--------| | `cast()` | Render all defined variables | | `cast(name)` | Render a specific variable | | `name.cast()` | Dot syntax (Obj-typed variables only) | Multiple `cast()` calls accumulate. The GUI provides a Render button that inserts `cast()` automatically when new variables exist since the last cast. ### Example ``` let a: Obj = sphere(3) let b: Obj = box(4, 2, 1) let c: Obj = translate(a, 5, 0, 0) cast() ``` This renders `a`, `b`, and `c` as a union. Without `cast()`, nothing appears. --- ## Plotting with `plot()` | Syntax | Effect | |--------|--------| | `plot()` | Plot all bare expressions | | `plot(expr)` | Plot a specific expression | The GUI provides a Plot button that inserts `plot()` when new expressions exist since the last plot. ### Example ``` sin(x) * exp(-x^2) plot() ``` --- ## Complete Example ``` // Bolt head: hexagonal prism with a sphere on top let head: Obj = 6-gon(3) let dome: Obj = translate(sphere(3.2), 0, 0, 1.5) let cap: Obj = intersect(head, dome) // Shaft let shaft: Obj = cylinder(1.2, 8) let bolt: Obj = union(translate(cap, 0, 0, 8), shaft) // Cross hole let slot: Obj = box(0.4, 3, 10) let slot2: Obj = rotate_z(slot, pi/2) let cross: Obj = union(slot, slot2) let final: Obj = diff(bolt, cross) cast(final) ``` ### Schematics + Iteration ``` // Reusable peg schematic sch Peg(r, h) { let shaft = cylinder(r, h) let head = translate(sphere(r * 1.5), 0, 0, h) union(shaft, head) } // Base plate with a ring of pegs let plate: Obj = box(20, 20, 1) let pegs: Obj = map(i, 0..8) { rotate_z(translate(Peg(0.5, 3), 8, 0, 1), i * pi/4) } let assembly: Obj = union(plate, pegs) cast(assembly) ```