Guide to Blank language

by Andrew Turley


I. INTRODUCTION

A few months ago I was introduced to a new concept in programming. It all started when I ran a Yahoo! search for "programming languages". I came across a programming langage called Befunge. Befunge opened up a whole new world of programming for me, a world unlike BASIC, C or Pascal. Programs were not expected to follow a certain form. There was no structure. The programmer had a set of commands and a playing field the size of the monitor. The programmer had the freedom to use these tools as he or she saw fit. I was inspired by Befunge and enjoyed writting programs in it, trying to find faster, smaller ways of doing things. Through Befunge, I was also introduced to Brainf*ck and False, two more programming languages which departed from the structure and rigor of other programming languages. The thing that impressed me most was that these languages were designed to be fun. They did not take themselves too seriously. They were like go karts: not meant for every day driving, but a whole lot of fun to play with.

As a spring break, I decided to try my hand at making a programming language (so much more fun than passing out in Cancun). What I got was Blank, a fun, ugly, interpretted language that borders on being useful. I tried to take all of the things that I liked about Befunge, False, and Brainf*ck, and combine them into one package. In some respects I feel short of this goal, but in others I managed to acheive it and even surpas it. Blank is not the best programming language ever. But it can be fun.

II. ANATOMY OF A BLANK PROGRAM

A Blank program contains two things: data and instructions. The program is a loop, meaning that when the "end" of a program is reached, then next instruction is actually the first instruction. For example, this program:
[2]{.}
is an infinite loop which prints "2" to the screen. Data are popped onto the stack when they are encountered. Instructions are executed when they are encountered. The program starts at the first "cell" (either a datum or an instruction) and moves right unless it encounters an instruction telling it to move somewhere else.

II.A DATA

Every computer langage has data that it manipulates. In most languages that are used today, data is stored in variables. For example, in C the line
a = 182;
stores the value 182 in a variable called "a". Blank, like Befunge, has no variables to speak of. Data are pushed onto the stack, where they are then manipulated. In a program, data is denoted by []. If you want the value 182, you would simply use
[182]

When this instruction is encountered, 182 is pushed onto the stack. The numbers pushed onto the stack can be between 0 and (2^31)-1 (the length of a signed long in C). If the number inside is any longer, you will have some problems.

There are a few things to keep in mind at this point. The first is that expressions betweeen [] are not evaluated. Therefore,
[2*2]
is not the same as
[4]

Another thing to remember is that you should not enter characters as values unless you know what you are doing, because characters will not be treated as characters.

For example,
[p]
will not result in "p" being pushed onto the stack. If you want to put an ASCII character on the stack, the easiest thing to do is to enter the ASCII value of the character onto the stack.

For example,
[112]
would push the ASCII value of "p" onto the stack. You cannot enter floating point numbers.

If you have
[1.34]
the value 1.34 will not be entered. Do not try it, it will not work.

Finally, you cannot enter negative numbers as data.
[-134]
will not be entered as -134. You can, however, subract a value from 0 to get the negative value, and you can then use the {'} command to put the negative value into a cell.

II.B INSTRUCTIONS

Instructions in blank are one character long. They are denoted by {}. The Blank instruction set can be broken down into three group:

II.B.1 STACK OPERATIONS

To start off a discussion about stack operations, one must first understand the concept of a stack. Imagine that you have a whole bunch of blocks with numbers written on them piled up on the floor. Grab a block and set it on the floor in front of you. You have just pushed a block onto the stack. Now grab another block and set it on the first one. You have just pushed another block onto the stack. You can can also take a block off the top of the stack. This is called popping. Once you pop a block off the stack, it is gone from the stack and the block underneth it now becomes the block on the top of the stack. You can push and pull blocks off the top of the stack, but you cannot push or pull them to other parts of the stack. For example, if your stack looked like this
10
12
563
9
14
where 10 is the top of the stack and 14 is the bottom, you could not just pop 563 off of the stack. You could, however, pop 10 off the stack, then pop 12 off the stack, and then pop 563 off the stack.

When you get bored with pushing and popping, you can begin to do math with the stack. Operations on the stack generally only involve the top two stack items. Lets go back to our stack of
10
12
563
9
14

You can add 10 and 12, subtract 10 from 12, multiply 10 by 12, divide 10 by 12 or take the modulus of 10 and 12.

Now, here are some concrete examples. To set up a stack of
10
12
563
9
14
you would use a program that looks like this
[14][9][563][12][10]

Notice that each number is placed on top of the last number that was entered onto the stack. Notice also that this program would do nothing but add these numbers to the stack forever. To stop it one would add {@} to the end, making the program look like this
[14][9][563][12][10]{@}
This program would set up the stack and then stop.

Now we can begin to do math. If we put a {+} between the [10] and the {@}, our program would look like this
[14][9][563][12][10]{+}{@}
The stack would now look like this
22
563
9
14
The 10 and the twelve were popped off, added together, and the result (which of course is 22) was pushed back onto the top of the stack.

Changing the {+} to a minus gives us the program
[14][9][563][12][10]{-}{@}
and results in a stack that looks like this
2
563
9
14
Notice that 10 was subtracted from 12. To write this out, it would be
12 - 10 = 2
It took me some time to get used to this because I kept thinking that it would be
10 - 12 = -2
It is important to remember the order in which the stack items are used in the operation.

Changing the {-} to a {*} gives us the program
[14][9][563][12][10]{*}{@}
and results in a stack of
120
563
9
14
because the 10 and 12 were multiplied together.

Changing the {*} to {/} gives us the program
[14][9][563][12][10]{/}{@}
and results in a stack of
1
563
9
14
Again this is the result of
12 / 10 = 1.2
but because Blank cannot handle floating point numbers, the .2 is dropped.

Changing the {/} to {%} results in
2
563
9
14
The 2 is the remainder of
12 / 10 = 1.2 = 1 remainder 2

Sometimes you will want to get rid of something on the stack. Consider the program
[2][3][4]{+}{@}
Assume that you wanted, for some reason, to add the numbers 2 and 3. In this program, the numbers 4 and 3 are added together. Let us start by looking at what the program does.

First, the value 2 is pushed onto the stack, and the stack looks like this
2

Then, the value of 3 is pushed onto the stack, and the stack looks like this
3
2

Then, the value of 4 is pushed onto the stack, and the stack looks like this
4
3
2

Then the {+} instruction is encountered. The 4 and the 3 are popped of, added together to produce 7, and the 7 is pushed back on to the stack. The stack now looks like this
7
2

If the {$} command is placed between the [4] and the {+}, it will pop the top value off the stack and discard that value. It is now gone forever, or until the program goes back over the [4] cell. The program would look like this
[2][3][4]{$}{+}{@}

The first few step would look the same as they did in the pervious example, until the step where 4 and 3 were added together. So we have the stack
4
3
2

Instead of the {+} command, the {$} command is encountered and 4 is popped off the stack, leaving a stack of
3
2

The the {+} command is encountered and the 3 and the 2 are added together, leaving a stack of
5

Finally, the {@} command is encountered and the program stops.

The {\} command swaps the top two stack values. Therefore, in the program
[2][3][4]{/}{@}
the stack goes from
4
3
2
to
3
4
2

The command {^} copies a stack item to the top of the stack. Consider the program
[6][5][4][3][2]{^}{@}
The stack looks like this
2
3
4
5
6
by the time the {^} command is encountered. The top item of the stack which in this case is 2, is then popped off. The stack now looks like this
3
4
5
6
Because a 2 was popped off, the second value on the top of the stack is now copied and pushed to the top. The stack now looks like this
4
3
4
5
6
When using this command, remember that if a 0 is on the top of the stack when the command is encountered, it simply pops the 0 off, just as if you had used the {$} command.

The {`} command pops two values off of the stack. If the second value is greater than the first value, it pushes a 1 onto the stack. Otherwise it pushes a 0.

The {!} command pops a value of the stack. If the value is 0, it pushe a 1 back onto the stack, otherwise it pushes a 0.

II.B.2 INPUT/OUTPUT

Blank provides several types of input and output. All of them either get a value from some place and push it to the top of the stack or pop a value off the top of the stack and put it somewhere.

The {~} command gets an ASCII input from the keyboard and pushes the ASCII value onto the top of the stack. The {&} command gets an integer input from they keyboard and pushes it to the top of the stack. The integer input may be between -(2^31) and (2^31)-1.

The {,} command pops the top value of the stack and puts the ASCII character represented by that value to the screen. The {.} command pops the top value of the stack and puts that value to the screen.

The {"} command pops a value off of the stack. We will call this value "distance". The value contained in the cell that is "distance" cells to the right of the current cell is then pushed onto the stack. Similarly, the command {'} pops a value off of the stack, which we will again call "distance". It then puts the pops the next value on the stack and puts it "distance" cells to the right of the current cell. There are a few things to remember about these commands. First, they get and put only to the right of the current cell. But since the program is circular, you can still reach any cell from any other cell. Another thing to remember is that a negative number will not get or put to the left. A value equal to or less than 0 will result in the contents of the current cell being accessed. Also, putting a value in a command cell (one denoted by {}) will result in a new command being put in that cell. The command depends on the value that is popped off the stack. It will NOT be treated as a value to be pushed onto the stack. The value will be treated as a value to be pushed onto the stack if the cell is already a data cell.

The {=} command gets the next character from the input file and pushes it onto the stack. The {_} command pops a value off the stack and writes the value to the output file. Remember that it only puts the lowest 8 bits of the value into the file, so it is a good idea to not write numbers greater than 255. The input file and output file are specified on the command line as the last two arguements. In MS-DOS it would look like this
C:\blank example.bl input.txt output.txt
This line would run the program example.bl and would use input.txt as the input file and output.txt as the output file. Input and output files are optional, but if you have an input file you must have an output file, and vice versa, even if you do not use one of them.

The command {?} pushes the number of cells in the program onto the stack. For example, when {?} is encountered in this program
[1][2][3]{?}{@}
the value 5 is pushed onto the stack because the program is 5 cells long.

II.C PROGRAM CONTROL

Some of the program control commands are easy to understand, others require a little thought and some practice to master. They can be a pain to use, but I tried to make it possible to write recursive functions. It just takes some work. They all use the program stack, separate from the stack that the other commands use. All references to the stack refer to the stack used by the other commands while all references to the program stack refer to the program stack. Do not get the two confused as they are not the same thing.

The {@} command is one of the easiest commands to understand. It simply stops the program and exits to the operating system.

The {>} command places the location of the current cell on the program stack. It then pops a value from the stack and jumps that many cells to the right of its current position. Like the {'} and {"} commands, values of 0 or less will not make the program jump to the right.

The {<} command pops a location off of the program stack and goes to the cell just to the right of that location. If there is no location on the program stack, the program simply moves to the right as if there had been no {<}.

The {|} command is an "if" command. It pops two values off the stack. If the first value is not equal to 0 then it acts like the {>} command using the second value as the arguement.

The {#} pops a value off the program stack and discards it. This way the {>} and {|} commands can work like goto commands in BASIC instead of gosub commands.

II.D PROGRAM MODIFICATION

There are two commands in blank which allow the program to modify itself. The {)} command pops a value off of the stack and then creates a new data cell that many cells to the right of the current cell. This new cell is empty. The {(} command works like the {)} command, only it destroys a cell a certain number of cells away from the current cell. Both commands change the number pushed onto the stack by {?} so that it still reflects the number of cells in the program. Remember that the {)} command creates data cells, not instruction cells, but that the {(} command destroys any kind of cell.

III. TIPS

Remember, the first value read will be the last value to be popped out. See some of the included example sources to see how this works and what this means for your progams.

IV. NOW WHAT?

Now that you know how to use Blank, you can use this programming language to write all kinds of programs. The sky is the limit. Well, I guess there are other limitations, but that does not matter. Just have fun with it.

Send all questions, comments, or Blank programs to Andrew Turley at aturley@sound.net

I will try to keep an updated list of all Blank programs at my web site

V. DISCLAIMER

Andrew Turley takes not responsibility for any problems that may arise as a dirrect or indirrect use of the Blank programming language.

Appendix A. BLANK COMMAND SUMMARY

x and y are used to refer to the first and second values popped off the stack.
commanduse
@stops the program, exits to operating system
>pushes current location on program stack, jumps x cells right
<pops location from program stack, returns to cell to the right of that location
+ add x and y
- subtract x from y
* multiply x and y
/ divide y by x
% modulo y with respect to x
| if x not 0, push current location onto program stack, jump y spaces
$ discard x
~ get ASCII value from keyboard, push onto stack
& get integer from keyboard, push onto stack
, output ASCII value represented by x to screen
. output integer value of x to screen
! negate x
: copy x
" push value x cells to right onto stack
' put value y into cell x cells away
` is y > x?
# pop and discard top value of program stack
\ swap x and y
= push character from input file onto stack
_ write character x onto output file
) create a new cell x cells to the right
( destroy cell x cells to the right
? push lenght of program (number of cells) into stack
^ copy x stack item to top of stack

If you have any questions about anything, look at blank.c


HTMLed by rms