diff --git a/docs/system.dj b/docs/system.dj new file mode 100644 index 0000000..3111b2f --- /dev/null +++ b/docs/system.dj @@ -0,0 +1,440 @@ +# haku system library + +haku comes with a set of built-in functions, called the _system library._ +This is a reference for these functions. + +## Preamble: how to read this reference + +Each function comes with a _signature description_. +These descriptions read like this: + +```haku +(stroke + (thickness number) + (color rgba) + (position vec) + scribble) +``` + +The first element is always the function's name - in this case `stroke`. +Following this are `(argument-name argument-type)` pairs, which describe the arguments that need to be passed to the function. +The last element is always the type of data this function produces. + +The argument name usually does not matter when calling the function - it is only used for documentation purposes. +The one exception is arguments called `...`, which signify that zero or more arguments can be passed to the function at that position. + +The argument _type_ however is important. +If you try to use a function with the wrong type of value as its argument, it will fail with an error. +For example, consider a brush where we pass a number as `stroke`'s `color` and `position` arguments. + +```haku +(stroke 1 1 1) +``` + +This brush will fail to render, since `stroke` expects an `rgba` as its 2nd argument. + +With that said, there are several types of values in haku that can be passed into, and returned by functions. + +- `*` - special type used to signify that any value may be passed into the function. +- `()` - also known as _nil_, means _no value._ +- `boolean` - either `false` or `true`. Indicates truth or falsehood, used in `if` conditions. +- `number` - a real number, with 32 bits of precision. +- `vec` - a 4-dimensional vector, composed of four `number`s. +- `rgba` - an RGBA color, composed of four `number`s. +- `fn` - a function, as returned by `(fn (x) x)` literals. +- `list` - a list of values, where each value can have a different type (even `list` itself.) +- `shape` - a mathematical shape. + - `shape-like` - anything that can be turned into a `shape` using `to-shape`. +- `scribble` - something that can be drawn on the wall. + +Additionally, the syntax `(type-a type-b ...)` may be used to signify that one of the listed types is accepted or returned. + +## Math + +```haku +(+ + (... number) + number) +``` + +`+` takes an arbitrary amount of arguments and sums them together. +When there are zero arguments, it returns `0`. + +```haku +(- + (a number) + (... number) + number) +``` + +When there is only one argument, `-` returns `a` with the opposite sign. +Otherwise, it performs an arbitrary amount of subtractions from `a`, and returns the result. +Note that unlike `+` and `*`, at least one argument must be present. + +haku does not have syntactic support for negative numbers - the proper way to negate a number is using this function `(- 1)`. + +```haku +(* + (... number) + number) +``` + +`*` takes an arbitrary amount of arguments and multiplies them together. +When there are zero arguments, it returns `1`. + +```haku +(/ + (a number) + (... number) + number) +``` + +`/` returns `a` divided by all the numbers from `...`. +Note that unlike `+` and `*`, at least one argument must be present. + +## Logic + +The following functions are used to compare values and work with `boolean`s. + +```haku +(not + (b *) + boolean) +``` + +If `b` is `()` or `false`, `not` returns `true`. +Otherwise it returns `false`. + +```haku +(= + (a *) + (b *) + boolean) + +(<> + (a *) + (b *) + boolean) +``` + +`=` returns `true` if `a` and `b` are equal. +Whether two values are considered equal depends on their type: + +- If the type of the two values differs, `false` is returned. +- If the two values are `number`s: + - If any of the values are `NaN`, `false` is returned. + - Otherwise `true` is returned if the two numbers have the exact same bit representation. +- If the two values are `vec`s, `true` is returned if each of their `number` components is equal to each other using the rules above. +- Likewise with `rgba`s. +- All other types of values use _reference_ equality - `true` is returned only if `a` and `b` are located in the same place in memory. + This more or less means that the values are considered equal if they are produced by the same call to a system function, in time. + +`<>` returns `(not (= a b))`. + +```haku +(< + (a *) + (b *) + boolean) + +(<= + (a *) + (b *) + boolean) + +(> + (a *) + (b *) + boolean) + +(>= + (a *) + (b *) + boolean) +``` + +`<` returns `true` if `a` is less than `b`, and `<=` returns `true` if `a` is less than _or_ equal to `b`. + +Order is only well-defined for numbers. +Other types may assume an arbitrary but consistent ordering - `()` may be less than `true`, or it may not be less than `true`, but this will not change between executions of the program. + +`(> a b)` is the same as `(< b a)`. +`(>= a b)` is the same as `(<= b a)`. + +--- + +Note that `and` and `or` are currently missing from this list. +You can implement them using regular functions as a replacement. + +```haku +(def and + (fn (a b) + (if a (if b true false) false))) + +(def or + (fn (a b) + (if a true (if b true false)))) +``` + +## Vectors + +```haku +(vec + vec) + +(vec + (x number) + vec) + +(vec + (x number) + (y number) + vec) + +(vec + (x number) + (y number) + (z number) + vec) + +(vec + (x number) + (y number) + (z number) + (w number) + vec) +``` + +Creates a new `vec` from zero to four number values. + +A `vec` always has four dimensions. +If any of the arguments are omitted, its corresponding dimension is initialized to zero. + +```haku +(.x + (v vec) + number) + +(.y + (v vec) + number) + +(.z + (v vec) + number) + +(.w + (v vec) + number) +``` + +`.x`, `.y`, `.z`, and `.w` extract the individual components of a `vec`. + +--- + +Note that mathematical operations are currently not defined for vectors. +You may define your own vector operations like so: + +```haku +(def +v ; Vector addition + (fn (a b) + (vec + (+ (.x a) (.x b)) + (+ (.y a) (.y b)) + (+ (.z a) (.z b)) + (+ (.w a) (.w b))))) + +; Likewise for subtraction, multiplication, and division. +``` + +Note that haku-defined vector operations like these are more costly the more components they operate on. +Therefore, it's recommended to only define them for two dimensions, unless you really need more. + +```haku +(def +v2 ; 2D vector addition + (fn (a b) + (vec + (+ (.x a) (.x b)) + (+ (.y a) (.y b))))) +``` + +## Colors + +```haku +(rgba + (r number) + (g number) + (b number) + (a number) + rgba) +``` + +Creates a new `rgba` with the given color channels. +Note that unlike `vec`, all color channels have to be provided to form an `rgba`. + +```haku +(.r + (color rgba) + number) + +(.g + (color rgba) + number) + +(.b + (color rgba) + number) + +(.a + (color rgba) + number) +``` + +`.r`, `.g`, `.b`, and `.a` extract color channels out of an `rgba`. + +--- + +haku uses RGBA values in a normalized `0` to `1` range rather than `0` to `255`, which may be unfamiliar if you're coming from other image editing software. +This is because it's easier to do math on normalized colors. +For example, consider multiplicatively blending two colors. + +```haku +; This is how you can multiply two colors together. +(def *rgba + (fn (a b) + (rgba + (* (.r a) (.r b)) + (* (.g a) (.g b)) + (* (.b a) (.b b)) + (* (.a a) (.a b))))) +``` + +If haku represented colors using an 8-bit `0` to `255` range instead, to multiply two colors together, you would have to divide them by `255` to get them back into the correct range. + +```haku +; NOTE: This example does NOT work correctly. +(def *rgba + (fn (a b) + (rgba + (/ (* (.r a) (.r b)) 255) + (/ (* (.g a) (.g b)) 255) + (/ (* (.b a) (.b b)) 255) + (/ (* (.a a) (.a b)) 255)))) +``` + +Note that haku does not clamp colors to the `0` to `1` range. +It is perfectly valid to have a color that is out of range or even `NaN`, but when drawing scribbles: + +- `∞` is clamped back to `1`. +- `-∞` is clamped back to `0`. +- any scribble with a `NaN` color is ignored. + +Note that just like vectors, arithmetic operations on colors are currently not defined. + +Before scribbles are drawn to the wall, colors are converted to 8-bit integers for more efficient rasterization and storage. +This means some loss of precision will happen, which may cause issues with brushes like this one: + +```haku +(stroke + 128 + (rgba 0 0 0 0.1) + (vec)) +``` + +If you try to to use this brush to fill up a single spot with black, you will notice that despite all the math suggesting so, the color will end up gray instead. + +## Data structures + +```haku +(list + (... *) + list) +``` + +`list` is used to construct a new list. + +Currently, lists do not have any operations defined on them. +However, lists made up solely of scribbles are scribbles themselves, which allows for combining scribbles together. + +## Shapes + +```haku +(to-shape + (value *) + (() shape)) +``` + +Converts the given value to a shape. + +- For `shape`, clones the shape that was passed in. +- For `vec`, returns a point `shape`. +- For anything else, returns `()`. + +```haku +(line + (start vec) + (end vec) + shape) +``` + +Creates a line segment shape with the provided `start` and `end` points. + +```haku +(rect + (position vec) + (size vec) + shape) + +(rect + (x number) + (y number) + (width number) + (height number) + shape) +``` + +Creates a rectangle shape with its top-left corner at `position`, with a given `size` stretching from the top-left corner. + +The alternative 4-argument version takes in the rectangle's X/Y coordinates, width, and height as separate arguments instead of aggregating them into a `vec`. + +```haku +(circle + (center vec) + (radius number) + shape) + +(circle + (x number) + (y number) + (radius number) + shape) +``` + +Creates a circle shape, with its center at `center`, with the provided radius. + +The alternative 3-argument version takes in the circle's center X/Y coordinates as separate arguments instead of aggregating them into a `vec`. + +## Scribbles + +```haku +(stroke + (thickness number) + (color rgba) + (shape shape-like) + scribble) +``` + +Creates a stroke scribble, which outlines the provided shape with a stroke of the given thickness and color. + +Point shapes are drawn as squares, and `line` shapes have square caps at the line's endpoints. + +```haku +(fill + (color rgba) + (shape shape-like) + scribble) +``` + +Creates a fill scribble, which fills in the entire area of the provided shape with a solid color. + +Since this requires the shape to have a surface area, this does not do anything when point and `line` shapes are passed in.