We can also define a bunch of other “primitive” operations, such as:

    1. # Logical unary not.
    2. def unary!(v)
    3. if v then
    4. 0
    5. else
    6. 1;
    7. # Unary negate.
    8. def unary-(v)
    9. 0-v;
    10. # Define > with the same precedence as <.
    11. def binary> 10 (LHS RHS)
    12. RHS < LHS;
    13. # Binary logical or, which does not short circuit.
    14. def binary| 5 (LHS RHS)
    15. if LHS then
    16. 1
    17. else if RHS then
    18. 1
    19. else
    20. 0;
    21. # Binary logical and, which does not short circuit.
    22. def binary& 6 (LHS RHS)
    23. if !LHS then
    24. 0
    25. else
    26. # Define = with slightly lower precedence than relationals.
    27. def binary = 9 (LHS RHS)
    28. !(LHS < RHS | LHS > RHS);
    29. # Define ':' for sequencing: as a low-precedence operator that ignores operands
    30. # and just returns the RHS.
    31. def binary : 1 (x y) y;

    Given the previous if/then/else support, we can also define interesting functions for I/O. For example, the following prints out a character whose “density” reflects the value passed in: the lower the value, the denser the character:

    Based on our simple primitive operations defined above, we can start to define more interesting things. For example, here’s a little function that solves for the number of iterations it takes a function in the complex plane to converge:

    1. # Determine whether the specific location diverges.
    2. # Solve for z = z^2 + c in the complex plane.
    3. def mandelconverger(real imag iters creal cimag)
    4. if iters > 255 | (real*real + imag*imag > 4) then
    5. iters
    6. else
    7. mandelconverger(real*real - imag*imag + creal,
    8. 2*real*imag + cimag,
    9. iters+1, creal, cimag);
    10. # Return the number of iterations required for the iteration to escape
    11. def mandelconverge(real imag)
    12. mandelconverger(real, imag, 0, real, imag);

    Given this, we can try plotting out the mandelbrot set! Let’s try it out:

    1. ******************************************************************************
    2. ******************************************************************************
    3. ****************************************++++++********************************
    4. ************************************+++++...++++++****************************
    5. *********************************++++++++.. ...+++++**************************
    6. *******************************++++++++++.. ..+++++*************************
    7. ******************************++++++++++. ..++++++************************
    8. ****************************+++++++++.... ..++++++***********************
    9. ***********************++++++++... ++*********************
    10. *********************+++++++++.... .+++********************
    11. ******************+++..+++++.... ..+++*******************
    12. **************++++++. .......... +++*******************
    13. ***********++++++++.. .. .++*******************
    14. *********++++++++++... .++++******************
    15. ********++++++++++.. .++++******************
    16. *******++++++..... ..++++******************
    17. *******+........ ...++++******************
    18. *******+... .... ...++++******************
    19. *******+++++...... ..++++******************
    20. *******++++++++++... .++++******************
    21. *********++++++++++... ++++******************
    22. **********+++++++++.. .. ..++*******************
    23. *************++++++.. .......... +++*******************
    24. ******************+++...+++..... ..+++*******************
    25. *********************+++++++++.... ..++********************
    26. ***********************++++++++... +++********************
    27. *************************+++++++.. . ... .++*********************
    28. **************************++++++++....... ......+++**********************
    29. ****************************+++++++++.... ..++++++***********************
    30. *****************************++++++++++.. ..++++++************************
    31. *******************************++++++++++.. ...+++++*************************
    32. *********************************++++++++.. ...+++++**************************
    33. ***********************************++++++....+++++****************************
    34. ***************************************++++++++*******************************
    35. ******************************************************************************
    36. ******************************************************************************
    37. ******************************************************************************

    At this point, you may be starting to realize that Kaleidoscope is a real and powerful language. It may not be self-similar :), but it can be used to plot things that are!

    Strikingly, variable mutation is an important feature of imperative languages, and it is not at all obvious how to add support for mutable variables without having to add an “SSA construction” phase to our front-end. In the next chapter, we will describe how we can add variable mutation without building SSA in our front-end.