Thinking about BooTer, I decide that I wasn't making it esoteric enough..so I've slimmed down my specification for simpler implementation, and much more difficulty doing anything useful with it :)
The only thing allowed is simple expressions and boolean ternary expressions. No comma-separated lists of expressions, no assigning expressions to variables, no symbols, no quoting of expressions.
Maybe in the future I'll re-expand it out into a more "real" language, but for now I just want to do something that I can do simply and easily without accidentally building an entire broken LISP.
So, with all that stuff gone..what's left? What's different now?
The boolean-ternary operator is in an order which won't drive me insane to write programs in. The boolean expression comes first. If true, the expressions evaluates to the second expression, if not, it evaluates to the third. This now works basically just like the ternary operator in most other languages...but with a different syntax and the possibility of using the re-eval operator.
A BooTer program is now a single boolean-ternary (booter) expression, with optional nested booter expressions.
The center portion of a booter expression (the "boo" part), must evaluate to either true or false. False is represented by the integer 0, or by null. Anything else is true.
null is represented by the lack of a value. This is useful for instances where the left or right portion of an expression will never be used, for example:
( ...do something here... : x = 5 : )
There are only numbers and strings as primitive types.
Variable names can start with upper or lowercase letters.
There's only a single array type. Array items are assigned and accessed using the standard  subscript operator. Creation of an array is implicit with the assignment of the first item to that array. If you use the subscript operator to make an assignment to a previously existing variable, the old variable is overwritten with the new array. The previous array literal syntax still applies. Only primitive values and variable names can be used in the array literal syntax.
Math and boolean order of operations are the same as in most programming languages these days.
The re-eval operator, ^, still works as previously stated.
Comments start with a semicolon and continue to the end of a line.
The previous example programs are both a bit more complex than they were previously (but hey, the parser and interpreter will be much easier to implement!):
Infinite NOOP loop:
( ^ : : )
100 bottles of beer:
(n = 101 :
(n = n-1 :
print [n, "bottles of beer on the wall!n"] :
In the beer example, assume that print prints the items passed into its array to the stdout and then evaluates to the same string it printed out.
While n is greater than 0, the sub-expression will evaluate to the string returned by print, which by the rules above equates to true, thus causing the re-eval operator to be evaluated, looping back to the expression (n = n-1).
When n finally gets assigned 0, the expression will evaluate to the third, empty, sub-expression, which equates to false, which means the center of the outer expression now evaluates to false as well, and thus the third expression of the outer expression is evaluated. It evaluates to null, which is the return of the program.
Here's a BooTer "for loop" with more of an explanation of what's going on:
(i = -1 : ; initialize loop variable
(100 > i = i + 1 : ; increment loop variable, check it against condition
... ; do things, must evaluate to true
... ; this one must evaluate to false (leaving it empty works)
^ ; re-evaluate this expression, causing the loop
... ; whatever can go here, this will be evaluated after the loop is done
: ) ; done, this last sub-expression will never be run
Even with this new "simplified" syntax, it's enough to make your head hurt. Now I just need to actually write a reference implementation with some standard library calls, then try to write something non-trivial with it. Who wants to try their hand at writing a BooTer web server?