Madeup
Madeup is a language for making things up. Using commands for moving around, its speakers walk interesting paths through 3-D space and generate geometric models tracing the paths. The models may be viewed in any standard 3-D model viewer or sent to a 3-D printer.
The language was designed for several reasons:
- To enable the creation of 3-D models through code. Some models are best sculpted with a mouse in a full-blown 3-D modeler. Others can be expressed more simply using a program.
- To teach math and computational thinking from a tangible, “first person” perspective. Madeup programmers build something out of nothing, giving them a high degree of creative involvement and responsibility in the construction process.
- To feed the diverse cravings of its designer, who loves programming languages and anything visual.
This document briefly describes the language.
Language
Madeup is a programming language—a language for instructing a machine to perform some action on its user’s behalf. Like most programming languages, Madeup lets its speakers
- repeat actions using loops,
- choose between alternative actions using conditional statements,
- abstract data into variables and process into functions,
- and manipulate data through builtin functions.
The language supports recursion, higher order functions, and partial function application.
Geometric Commands
Programmers traverse 3-D space using Cartesian or turtle geometry.
moveto <x> <y> <z>
move <distance>
yaw <degrees>
pitch <degrees>
roll <degrees>
Once a satisfactory path has been traversed, that path can be turned into a geometric model in several ways:
tube
revolve <degrees>
dots
surface <nrows> <ncolumns>
extrude <direction> <height>
forget
Let’s explain these through examples. Consider the following Madeup program, which walks from (3, 0, 0) in the Cartesian coordinate system in a roundabout way to (3, 2, 0):
moveto 3 0 0
moveto 7 0 0
moveto 7 2 0
moveto 3 2 0
tube
Using tube
to generate the geometry, we produce a model that surrounds the path with a hose-like structure:
If instead of tube
we use the revolve
command, we spin the path around an axis to produce a surface of revolution:
If we use the dots
command, we mark each stopping point along the path with a sphere:
If we use all three of tube
, dot
, and revolve
, we get a medley:
If we use the forget
command, we throw away the path without generating any geometry. This is like lifting the pen in Logo:
The surface
command doesn’t produce anything meaningful for the above program. Let’s switch to a new program, which visits a 3×3 grid of positions, the center of which is peaked upward:
-- Closest row
moveto 0 0 0
moveto 1 0.5 0
moveto 2 0 0
-- Middle row
moveto 0 0.5 1
moveto 1 1 1
moveto 2 0.5 1
-- Farthest row
moveto 0 0 2
moveto 1 0.5 2
moveto 2 0 2
surface 3 3
Unlike the other commands, the resulting model is not a solid object:
The last command, extrude
, treats the path as the perimeter of a solid object’s base. It pulls the perimeter up some specified height and fills in walls, floor, and ceiling. In the following example, we trace the path of a star and then extrude it 5 units along the negative Z axis:
moveto 0 0 0 repeat 5 move 10 yaw -144 move 10 yaw 72 end extrude 0 0 -1 5
Flow Commands
Besides commands to move and orient in 3-D space, Madeup has commands for controlling which commands are executed and how often:
if <condition> <then-block> else <else-block> end
repeat <n> <block> end
while <condition> <block> end
for <identifier> to <upper-bound> <block> end
for <identifier> through <upper-bound> <block> end
for <identifier> in <lower-bound>..<upper-bound> <block> end
Let’s start with a simple repeat
loop. We surround a block of commands with a repeat
loop and quantify how many times we’d like that block to execute. In the following program, we move 5 units forward and turn right 30 degrees—and then we do this four more times:
moveto 0 0 0
repeat 5
move 5
yaw 30
end
tube
We get a curved tube:
Loops can nest inside of each other. In the following program: we walk along a 5×5 grid using two for loops and generate a sphere at each location:
for r to 5
for c to 5
moveto c 0 r
end
end
dot
Conditional statements let us choose between commands based on some criteria. We can perturb a walk along a straight line, for example, by having one step zig and the next step zag. If we’re on an even step, let’s perturb right. Otherwise, let’s perturb left:
for i to 10
if i % 2 == 0
moveto 0.5 i 0
else
moveto -0.5 i 0
end
end
tube
New Commands
If we have a sequence of code that represents a meaningful action, we can give it a meaningful name. This name becomes a new command, which we can use to execute the sequence. In the following program, for example, the code to draw a square is given the name square
. We invoke the square
command whenever we want a square to be drawn:
to square =
repeat 4
move 10
yaw 90
end
tube
end
moveto 0 0 0
square
moveto 5 -5 0
square
Variables
Numbers in Madeup programs can also be given names. The benefits are twofold. Mathematical expressions that use variables are easier to make sense of, and it’s easier to try out different values if the number isn’t sprinkled throughout the code. To draw a regular, n-sided polygon, we might use the following program:
n = 5
angle = 360.0 / n
moveto 0 0 0
repeat n
move 5
yaw angle
end
tube
The value of n can be changed freely to generate hexagons, heptagons, octagons, nonagons, and so on.
Special Variables
Madeup relies on a few special variables when generating geometry:
nsides -- Defines the smoothness of the geometry (tube, dot, revolve)
radius -- Defines the girth of the geometry (tube, dot)
axis -- Defines the direction of motion (revolve, extrude)
By assigning different values to these variables, we can generate a snowman with varying levels of facetedness and body segment size using the dot command:
nsides = 6
radius = 1
moveto 0 6.5 0
dot
nsides = 15
radius = 2
moveto 0 4 0
dot
nsides = 50
radius = 3
moveto 0 0 0
dot
Recursion
Madeup supports recursion, where functions call themselves. The following program, for example, recursively generates a Hilbert curve:
size = 10 to hilbert level degrees = if level > 0 yaw degrees * -1 hilbert level - 1 degrees * -1 move size yaw degrees hilbert level - 1 degrees move size hilbert level - 1 degrees yaw degrees move size hilbert level - 1 degrees * -1 yaw degrees * -1 end end moveto 0 0 0 hilbert level:4 degrees:90 tube
Where Can I Find It?
The language and its execution environment are under active development. You can try it out at http://madeup.club:9013.