Try is the first esoteric programming language that I made. It uses exception handling, a feature found in many languages (such as C++ and Java) as its only control structure. Exceptions in try are simple strings indicating the type of error.
Contents
Statements
A Try program consists of several statements, entered one per line. The following types of statements are available:
- Assignment
- The simplest type of statement; consists of the name of a variable (letters, numbers, underscores; can't start with a number) followed by an expression. No equals sign or other symbol should be between the variable name and the expression. Expressions can contain variables (though see below), numbers, strings (enclosed in quotes with possible escapes
\n
, \\
, \"
), sqrt(expression)
(for square roots), addition, subtraction, multiplication, division, and string concatenation (using &
).
- try, catch, end
- A
try
block is a group of statements that has one or more catch
blocks. Each try
block starts with a line consisting only of the word try
and ends with a line consisting of only the word end
. A catch
block starts with a line containing catch
followed by the name of an exception (or the word all
) and continues until the next catch
block or the end of the try
block. When an error of the type named in a catch
block occurs while the code in the try
block is running, control jumps to the catch
block. For example:
output "If code here divides by zero, the program will just stop"
try
output "But here it won't"
output 1/0
output "This statement will never run"
catch divzero
output "This statement will run after the 1/0 line"
catch negsqrt
output "This statement will never run, because there are no sqrts"
end
output "This statement will run last."
- retry
- When used in a
catch
block, restarts the try
block that caused the exception. This is the only way to get a loop.
- macro, call
- A macro is defined by a block starting with
macro macro_name args
and ending with end
. It's called with call macro_name args
, where args
must be variables (not arbitrary expressions). Macros may not recurse. How the language handles macro arguments is left as an exercise to the reader.
Comments may be used by assigning a string to an unused variable. Expressions evaluated for their side effects must also be assigned to an unused variable.
Variables
While most variables can be read to and written from normally, there are several variable names that are treated specially:
- output
- Set this variable to change what is displayed in the output area. Read from this variable to find the current output. For compatibility with future implementations of this language, it is recommended that you only use this variable in statements of the form
output output & something
.
- input
- Read from this variable to prompt the user for input. The input always comes back as a string; see
number
below.
- rand
- Read from this variable to obtain a random number between 0 and 1. Set this variable to seed the random-number generator.
- number
- If you write a string to this variable and then read from it, instead of the string you wrote you'll find a number there instead (as long as the string represents a number). You'll need to do this if you want to do any math on user input.
- int
- Write a number to this variable and then read from it, and you'll get the number truncated to an integer.
- array
- The array currently being used. The only way to work with an array is to put it into this variable.
- arsize
- The size of the current array. Write to this variable to create a new array of the specified size.
- arvalue
- The value of the
arindex
th element (zero-based) of array
. Write to this variable to change the array.
- throw
- Write a string to this variable to throw an exception (i.e., cause an error) of the type indicated by the value. Read from this variable to find the last error that occurred.
- current_time (JS only)
- The current time, expressed as milliseconds since 1970-01-01T00:00:00z. Assigning this to a date in the future will cause the program to wait.
- input_mode (JS only)
- If set to the value "char", input will return as soon as a single character is entered, rather than waiting for the user to press return/enter.
- pi
- Initially the ratio of the circumference of a circle to its diameter. This is a normal variable that can be reassigned.
- tau (JS only)
- Initially the ratio of the circumference of a circle to its radius. This is a normal variable that can be reassigned.
- e
- Initially the base of natural logarithms. This is a normal variable that can be reassigned.
- inf
- Initially positive infinity. This is a normal variable that can be reassigned.
- null
- Initially the special "null" value that all unassigned variables initially have. (This is the only variable guaranteed to be unassigned at the beginning of the program.) This is a normal variable that can be reassigned.
Exceptions
- badcall*
- A macro was called with the wrong number of parameters.
- badchar*
- A statement contained a syntax error.
- badnumber
- The
number
variable was assigned a string that contained something other than a number.
- badthrow
- The
throw
variable was assigned something other than a string.
- divzero
- A mathematical expression attempted to divide by zero. Try using
inf
.
- endofline*
- A statement contained a syntax error, possibly because you didn't finish typing the
- middleofline*
- A statement contained a syntax error, namely that the line should have already ended.
- missingrparen*
- An expression contained a syntax error, namely mismatched parentheses.
- negarray
- An array was created with a negative size.
- negsqrt
- A mathematical expression attempted to take the square root of a negative number.
- noelement
- An attempt was made to access an array element outside the array.
- notimplemented
- A feature was not implemented by the interpreter
- nomacro*
- A
call
statement referenced a macro that was never defined.
- notanarray
- An attempt was made to perform array operations on a value that wasn't an array.
- notanumber
- An attempt was made to perform numerical operations on a value that wasn't a number. Try using the
number
variable.
- notimetravel
- current_time was set to a time in the past.
- null
- An attempt was made to use a variable that was not yet assigned (or that was assigned null).
- recurse*
- An attempt was made to define a recursive macro.
- unclosedtry*
- A try block or macro did not have an
end
.
- unopenedtry*
- An
end
didn't have a try block or macro, or a catch block didn't have a try block to go in.
Exceptions marked with asterisks are syntax errors; it is not guaranteed that any program that can cause these errors will compile (and therefore be able to handle them in a catch
) block. The asterisk is not part of the name of the exception. Additional exceptions can be used by assigning the throw
variable.
Version differences
- Some parser differences:
- Whitespace at the end of a line is ignored in the JS version; in the Java version, putting a space after a "try" statement is an error
- In the JS version, most things can be used in a catch handler; in the Java version, only valid variable names can be used
- Possibly some others...
- In the Java version, most syntax errors were reported before the program started executing (but still had exception-like names). In the JS version, they're exceptions that occur at runtime and can be caught.
input
is case-sensitive in the Java version, but case-insensitive in the JS version for consistency with other variables that do things when you assign to or read from them.
- Special variables
current_time
, input_mode
, and tau
are new in the JS version.
- The JS version has a new message if you don't type any code or delete the prompt to type code here. It also restores (and slightly changes) some Easter egg predefined variables from the original unpublished version that weren't in the applet (or downloadable). Oh, and there's a new variable
code
in the JS version.
- The JS version has saving, and some example programs. Most of the example programs are from 2006-7, but some are new: Hello world, Quine, and Unlambda interpreter are new.
- In the JS version, due to implementation details, variables won't always stay between executions of the program if you click Stop. Of course, the fact that variables stay between executions at all was always an undocumented feature (except for here).
- In the Java version, setting
rand
only has an effect if the value is a number; in the JS version, it always has an effect.