742 lines
16 KiB
Plaintext
742 lines
16 KiB
Plaintext
# System library




haku comes with a set of builtin 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 `argumentName : argumentType` 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.




Function names which are made up of symbols instead of letters are _operators_.


Operators may have one or two arguments, where one argument corresponds to a prefix form `x`, and two arguments correspond to an infix form `x  y`.


Note that this documentation lists a unary and binary operator of the same spelling as _two separate functions_, not overloads of a single function.




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.


(Currently there are no functions that accept any number of arguments, though.)




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 4dimensional vector, composed of four `number`s.


 `rgba`  an RGBA color, composed of four `number`s.


 `\a > r`  a function taking in the parameter `a` and returning `r`, as returned by `\x > x` literals.


 `list t`  a list of values, where each value is of the type `t`.


 `shape`  a mathematical shape.




 `shapeLike`  anything that can be turned into a `shape` using `toShape`.




 `scribble`  something that can be drawn on the wall.


 `reticle`  an interaction the user can make with the wall.




The syntax `a  b` may be used to signify that one of the listed types is accepted or returned.




The following syntax:




```haku


{


A : t


B : u


}


```




is used for _records_functions which take in a tag as a parameter, and return a value depending on what tag was passed.


In the case above, if `A` is passed in a value of type `t` is returned, and if `B` is passed in a value of type `u` is returned.


Passing in any other tag is an error.






## Math




```haku





a : number


> number







a : vector


> vector


```




``, when used in its unary form `x`, returns the number `x` with the opposite sign.


When used on vectors, returns the same vector facing the reverse direction (the individual components are negated.)




This operation is not defined for colors, because it doesn't make sense to have a color with negative RGBA values.




```haku


+


a : number


b : number


> number




+


a : vector


b : vector


> vector




+


a : rgba


b : rgba


> rgba


```




`+` adds two numbers, vectors, or colors together.




```haku





a : number


b : number


> number







a : vector


b : vector


> vector







a : rgba


b : rgba


> rgba


```




``, when used in its binary form `x  y`, subtracts two numbers, vectors, or colors from one another.




```haku


*


a : number


b : number


> number




*


a : vector


b : vector


> vector




*


a : rgba


b : rgba


> rgba


```




`*` multiplies two numbers together.


When used on vectors, it scales them componentwise.


Likewise for colors.




```haku


/


a : number


b : number


> number




/


a : vector


b : vector


> vector




/


a : rgba


b : rgba


> rgba


```




`/` divides a number by another number.


When used on vectors, it divides them componentwise.


Likewise for colors.




```haku


floor


x : number


> number




ceil


x : number


> number




round


x : number


> number


```




`floor`, `ceil`, and `round` are rounding functions.


Each of them rounds a little differently:




 `floor` rounds towards ∞.


 `ceil` rounds towards +∞.


 `round` rounds half towards +∞.




```haku


abs


x : number


> number


```




`abs` returns the absolute value of the given number.




If `x` is less than zero, returns `x`.


Otherwise returns `x`.




```haku


mod


x : number


y : number


> number


```




`mod` is the modulo operation.




It returns the remainder of dividing `x` by `y`.


haku uses the Euclidean definition, which means the remainder returned by `mod` is _always nonnegative_.




```haku


pow


base : number


exponent : number


> number


```




`pow` raises `base` to the given `exponent`.




```haku


sqrt


x : number


> number




cbrt


x : nunber


> number


```




`sqrt` returns the square root of the given number.




`cbrt` returns the cubic root of the given number.




Other roots may be obtained using `pow x (1 / base)`.




```haku


exp


x : number


> number




ln


x : number


> number


```




In the following functions, `e` is the base of the natural logarithm (approximately `2.7128`.)


The `e` constant (Euler's number) is currently not exposed to haku source code; you have to define it yourself.




`exp` is the exponential function `pow e x`.




`ln` is the natural logarithm (logarithm base `e` of `x`.)




```haku


expMinus1


x : number


> number




ln1Plus


x : number


> number


```




`expMinus1` is `pow e x  1`, but accurate even when `x` is close to zero.




`ln1Plus` is `ln (1 + x)`, but more accurate than if the operations are performed separately.




```haku


exp2


x : number


> number


```




`exp2` is the exponential function `pow 2 x`.




```haku


log2


x : number


> number




log10


x : number


> number


```




`log2` is the logarithm base `2` of `x`.




`log10` is the logarithm base `10` of `x`.




```haku


hypot


x : number


y : number


> number


```




`hypot` is the hypotenuse of the Pythagorean triangle with right angleadjacent sides `x` and `y`.




```haku


sin


x : number


> number




cos


x : number


> number




tan


x : number


> number


```




`sin`, `cos`, and `tan` are the [trigonometric functions][] sine, cosine, and tangent.


Their argument `x` is counted in radians.




[trigonometric functions]: https://wikipedia.org/Trigonometric_functions




```haku


asin


x : number


> number




acos


x : number


> number




atan


x : number


> number


```




`asin`, `acos`, and `atan` are the [inverse trigonometric functions][] arc sine, arc cosine, and arc tangent.


Their argument `x` is counted in radians.




[inverse trigonometric functions]: https://wikipedia.org/Inverse_trigonometric_functions




```haku


atan2


y : number


x : number


> number


```




`atan2` is the angle between the positive X axis and a line that passes through `(0, 0)` and `(x, y)`.




Note the reverse argument order`y` comes first, due to `atan2` being a convenience function over `atan (y / x)` that is defined for all arguments.




```haku


sinh


x : number


> number




cosh


x : number


> number




tanh


x : number


> number




asinh


x : number


> number




acosh


x : number


> number




atanh


x : number


> number


```




`sinh`, `cosh`, `tanh`, `asinh`, `acosh`, and `atanh`, are the six [hyperbolic functions][].




[hyperbolic functions]: https://en.wikipedia.org/wiki/Hyperbolic_functions






## Logic




The following functions are used to compare values and work with `boolean`s.




```haku


!


a : _


> 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 `!(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 welldefined 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, but are reserved keywords.


You can implement them using regular functions as a replacement.




```haku


boolAnd = \a, b >


if (a)


if (b) True


else False


else False




boolOr = \a, b >


if (a)


True


else


if (b) True


else False


```






## Vectors




```haku


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 one 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


vecX


v : vec


> number




vecY


v : vec


> number




vecZ


v : vec


> number




vecW


v : vec


> number


```




`vecX`, `vecY`, `vecZ`, and `vecW` extract the individual components of a `vec`.









## 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


rgbaR


color : rgba


> number




rgbaG


color : rgba


> number




rgbaB


color : rgba


> number




rgbaA


color : rgba


> number


```




`rgbaR`, `rgbaG`, `rgbaB`, `rgbaA` 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.


 Note that the `*` operator works for colors, so you don't need to define this in your brushes.


mulRgba = \a, b >


rgba (rgbaR a * rgbaR b) (rgbaG a * rgbaG b) (rgbaB a * rgbaB b) (rgbaA a * rgbaA b)


```




If haku represented colors using an 8bit `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.


mulRgba = \a, b >


let red = (rgbaR a * rgbaR b) / 255


let green = (rgbaG a * rgbaG b) / 255


let blue = (rgbaB a * rgbaB b) / 255


let alpha = (rgbaA a * rgbaA b) / 255


rgba red green blue alpha


```




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:




 any number less than `0` is clamped to `0`.


 any number greater than `1` is clamped to `1`.


 `∞` is clamped back to `1`.


 `∞` is clamped back to `0`.


 any scribble with a `NaN` color is ignored.




Before scribbles are drawn to the wall, colors are converted to 8bit 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 #00000004 (vec 0 0)


```




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.






## Lists




```haku


len


l : list _


> number


```




Returns the number of elements in the given list (its `len`gth.)




```haku


index


l : list t


i : number


> t


```




Returns an element of the list, located at the given index `i`.


The first element is located at index 0.




Indexing out of bounds is an error.






## Shapes




```haku


toShape


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 topleft corner at `position`, with a given `size` stretching from the topleft corner.




The alternative 4argument 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 3argument 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 : shapeLike


> scribble


```




Creates a stroke scribble, which outlines the provided shape with a stroke of the given thickness and color.




Point shapes are drawn as circles, and `line` shapes have round caps at the line's endpoints.




```haku


fill


color : rgba


shape : shapeLike


> 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.






## Reticles




```haku


withDotter


cont : \{


To : vec


From : vec


Num : number


} > scribble


> reticle


```




The dotter is a reticle that allows the user to draw things on the wall directly under the mouse cursor.


Once the user makes the interaction (presses the left mouse button), `cont` is called repeatedly with every movement of the mouse cursor, until the mouse button is released.




::: aside




It's not called a _plotter_ since the dotter does not plot lines or curves; it only places dots under the mouse cursor.




:::




During the interaction, `cont` is called with a record containing the following fields:




 `To`  the current position of the mouse cursor


 `From`  the previous position of the mouse cursor. May be equal to `To` if the user just pressed the mouse button.


 `Num`  the number of times `cont` has been called since the mouse cursor was pressed. Always greater or equal to `0`.




Since the dotter reticle finishes immediately (there is no extra interaction the user needs to take after pressing the mouse button for the action to be taken,) `cont` may only return a scribble; never another reticle.




The drawing area is a large, square, chunkaligned perimeter around `To`.
