If
the movie Pi contains any real insight into the
world, then everything on earth has a spiral nature. This
includes everything made by man, including computers and
computer programs. If computer programs have an inherent
spiral nature, why does the code we use to create them always
look like straight lines?
After
poking around the internet at various esoteric programming
languages, including programs that are hard to read, like
Brainf*ck, and its clones (Ook, Cow, f*ckf*ck), languages
that are written, it seems, entirely as jokes, like hq9++,
haifu, SMETANA, Whitespace, and, although its authors seem
to be fairly serious in their goals, INTERCAL, I was most
impressed with the languages that allow execution of two-dimensional
code, and allow the program pointer to move in any direction.
Such languages as Piet, BDAMD, Weird, and of course, Befunge-93,
are not only fairly capable, but their program sources are
fun to look at. Therefore, I set out to make a similar,
and yet far more capable language. After a few minutes of
thought, I came up with the basic idea for Spiral, a Turing-complete
language capable of far more than your typical BF or Befunge
program, and yet just as fun to code in. It contains aspects
of Befunge, Reverse, and Q-Bal.
Like
Befunge, Spiral's program pointer can start anywhere and
move up, down, left, or right. Unlike Befunge, it cannot
move across whitespace. The program pointer only moves to
a given location if there is a command there. As soon as
the pointer moves to a location, it will look to the right
for a command (unless it's looking to the left first, see
spiral (@) operator below), and if it finds one, it will
execute it. If the command it has just executed gives it
permission to, it will then move onto that command's location.
If the pointer finds no command (i.e., it finds a space
or nothing at all), it will attempt to go straight. If it
finds a command directly in front of it, it will execute
it, and, again, if it receives permission, will move to
that commmand's location. Otherwise, it tries to turn left
(unless it is now trying to turn right, see spiral (@) operator
below), and if once again it is blocked, it tries to go
back the way it came. If it can't go that way, you have
created an infinite loop (Oops!). Note that the top and
left edges of the program cannot be crossed (sorry, Befunge
programmers, no wrapping allowed) and behave exactly like
whitespace.
All
data in Spiral is contained in a single FIFO (push-down)
stack. However, thanks once again to our friend the spiral
(@) operator, the stack can function as both a FIFO and
FILO stack at the same time, and, despite any operator to
do so, any of its elements can be accessed. Each element
is a byte, and may contain a signed integer. There is also
a utility variable, which you may call villanova. This temporarily
stores values that are popped from, or are about to be pushed
to the stack.
There
are 16 operators in Spiral. Several of them do several things
at once. This serves three important purposes by increasing
functionality, decreasing program readability, and making
the language a bit trickier to use. The operators in Spiral
are:
Character
Name
Operation
@
spiral
The spiral
operator both alternates the default direction of program
flow and reverses the stack (so that you're looking
at it from the other end, and the bottom value is now
the top, etc.)
!
heyyou
The
heyyou operator immediately terminates the program.
*
star
When villanova
eats a star, it increments his value.
#
crosshatch
When villanova
trips on a crosshatch, it decrements his value.
v
push
The push operator
pushes villanova to the stack.
=
bridge
The bridge
operator does absolutely nothing.
X
railroad
The
railroad operator is the primary decision making operator.
It does three things. First, it pops the stack. If the
value it gets is zero, it hands it to villanova, and
allows the program pointer to come to its location.
If it gets a non-zero value, it takes offense, and tells
the program pointer to "bugger off" and throws
the value it got at it. Fortunately, villanova is very
patient, and always picks it up.
~
compare
The compare
operator compares the top two values on the stack, and
pushes -1 if the first is less, 0 if they are equal,
and 1 if the first is greater.
+
add
The add operator
pops the top two off the stack, and pushes back their
sum. This is provided purely for convenience, because
it can be entirely replaced with other Spiral code.
(see below)
.
cough
The cough operator
pops the stack and coughs the value as a unicode char
to STDOUT
,
spit
The spit operator
pops the stack and spits its numeral value to STDOUT
:
chew
The chew operator
chews up a unicode char from the input buffer and swallows
it to the top of the stack. If the input buffer is empty,
it gets more input from STDIN. A zero is pushed if the
user enters nothing.
;
swallow
The swallow
operator swallows a signed integer from STDIN to the
top of the stack.
^
copy
The copy operator
tells villanova what value the top of the stack contains,
and villanova promptly sets himself to this value.
&
random
Replaces the
top byte on the stack with a random integer less than
or equal to that number. Will cause an internal error
if byte is negative.
$
swap
The swap operator
swaps the top two values on the stack.
"
quote
This
operator is reserved for implementation in Spiral 2.
JSpI-2 will not be backwards-compatible with Spiral
programs containing this operator as a label.
any
other displayable character
label
Labels
do four things. First they set villanova to zero, the
pointer facing right, and the default turning direction
to the right, then they jump the pointer to the matching
label elsewhere in the program. Thus, they serve as
function calls, gotos, and make things like static object
code possible. Three or more of the same label in a
program will cause some very strange behavior, but will
not create an error. One by itself will cause a bad
label error. There is one special system label '0' that
determines where the program starts, and more than one
'0' will also cause strange behavior.
Of
course, that last trick, the label, means that comments
are impossible in a working Spiral program. Don't worry,
you can stick your comments in a separate file. Besides,
Spiral code looks so nice you don't want to spoil it with
comments cluttering up your source.
Examples
Here's
an example program in Spiral:
MULT:
0;;m,! =@=@= ====== X = = X $+v@ @m===@v@v$vX== ^ == X X #v$@ =X v =====@ = $ = X ======
MULT
takes two numbers from the user (either or both of which
may be negative) and pushes back their product, without
affecting the rest of the stack.
The
program above actually works. The program I had here before
didn't work, but I went into an in-depth analysis of it
anyway. Now that I have spent a few hours coming up with
a working solution, I leave it to the reader to figure
out how it works.
The
Aesthetics of Spiral
Spiral
programs are much more beautifuller than other languages.
How many languages are there where you can make your program
look like what it does? Take for example this HELLO WORLD
Program:
Who
cares that half the code serves no purpose? Or that the
same program can be written in just a few lines? How many
HELLO WORLD Programs are there whose source code spells
out HELLO WORLD in big block letters?? Who could mistake
this program for any other?
Object
Code
Spiral
is a unique language in that it is the most simple language
in which static objects with functions can be created.
To create an object use something like the following:
@o=*v^~*v^~*v^~ ==X X X X = X X X = f g h = @ @ @ ===============
o is your object. f, g, and h are all functions of o that
return a single non-zero value on top of the stack. To
call h via o, simply push 3 to the stack, and jump to
o. Isn't it cool? Of course, you may not make other calls
to f, g, or h, but isn't that the way objects work anyway?
Errors
There
are no language errors in Spiral (see label above). My
interpreter, however, will complain if you program is
too long, tall, or wide. There are three fatal runtime
errors, and that's trying to perform operations on an
empty stack, or pushing values onto a full stack, or misusing
labels. The former will terminate and send "Empty
Stack" or "Full Stack" and the pointer's
location to STDOUT. (The top left corner of the program
is called [1,1].) A bad label error is any labeling error
(such as a singular label) that causes the program pointer
to leave the program area, and will give a "Bad Label"
error message, and the name of the faulty label. Any other
errors in Spiral are logic errors. This makes debugging
a whole lot more fun of course.
More
Examples:
The
ADD program does the same thing as the + operator. This
is the simplest and most elegant program I have ever seen
in Spiral. The fact that this program works so well is
convincing evidence that I should scrap the + operator
in Spiral-2.
0;;a,!
==X a=v = = =XX=$v* #v$=X
The
FACT program computes a factorial. It requires the body
of the MULT program to be in the same file.
0;f,! v^ ========= =$ =@ ==== X =m ==f==vv$a========X =v = X v**v~ =v =*X== =v*= =# == == a^ =# ====@ v# X
The
SHUFFLE program takes the top of the stack as an argument
and shuffles the rest of the stack up that number of times.
(I.e., if the stack were a deck of cards, it would be
cutting that number of cards to the bottom.)
==XX ===v^== s=vv=X=$v= v =X X = # ===@v@X
The
CLEAR program clears the input buffer up to the next newline.
It's a good idea to run this if you've gotten all the
input you need for now, but may want more input later.
Remove the red X to pass
the entire input buffer (except the terminating newline)
onto the stack as a "string." Remove the green
X to pass the newline to
the stack as well.
XX =X==== = XX cvvX=~v*****= :$^$*****
The
following code will allow two lines of code meeting at
a perpendicular intersection to cross paths without interference.
To see some more interesting results, try adding or removing
bridges in the four spots diagonally adjacent to the center
of the intersection.
=
=
=@
===@@@====
=@
=
=
Challenges
These
are the challenges I would like to be met with this language:
A
compiler that will compile Spiral source code directly
to JAVA byte code (something I have no idea how to write).
A
quine
A
good-looking ASCII art picture of a dragon that prints the
dragon's name when executed.
A
program that does the same thing when compiled in Whitespace
as it does in Spiral. (Keep in mind that [TAB] and [SPACE]
are considered to have the same width in Spiral, so this
program's source may not line up so neatly.)
Any
combination of the above (a dragon ascii art program that
prints its source code in Spiral and Whitespace being the
ultimate goal).
Interpreters
JAVA
Interpreter Source(18.5 KB)-Compile this yourself. New
in v1.1: The ` character will toggle debug mode on and off.
According to my specification ` should be a label, but my
interpreter doesn't have to follow my specification does it?
Spiral
2
Coming
some time next year will be JSpI-2 with my new Spiral 2 spec.
It will not only do away with all the unnecessary fluff of
Spiral, and be far easier to code in, but it will provide
operations for self-modifying code, and code with multiple
pointers (akin to multi-threading). Function calls and object
code will be easier to create, and comments will be possible.
Most importantly, a Spiral 2 library will be created that
will simplify all the most basic of Spiral tasks, and since
it will be written in Spiral 2 itself, it will remain true
to the Esoteric Programming Dream. JSpI-2, when complete,
will still be able to run original Spiral programs.
Contact
If
you like to amaze me with your Spiral source code, or have
any questions about the language, or this website, please
send to Quintopia.
Website designed and built by
Quintopia in 2003.
Like it? Want your own site designed. David knows how.
Experience in PHP, MySQL, JavaScript, Java,
and HTML.
Work done cheap! Email Quintopia.