Ueck

From Esolang
Jump to navigation Jump to search

Ueck is an expression-based esolang by User:BoundedBeans.

Syntax

There are only two expression types in this language.

An item is either an unsigned 31-bit integer (0-2147483647) or an operator. Operators are one of the characters +-*/@=!?.

A compound expression is written as three expressions separated by spaces and surrounded by parenthesis.

Examples:

(36 + 58)
(2002 / 5)
(/ + !)
(* 4 =)
((4 + 9) / 5)
(14 (62 = =) (5 5 6))

An expression can be followed by :: and any sequence of non-space non-parenthesis characters, which represents a comment and is the same thing as the expression before it. There must not be any whitespace separating the last character of the expression from the colons.

Evaluation

First of all, runtime items can actually be values other than those described in the syntax, but they don't have syntax and have to be created out of the other features. This matters mostly for extensions to the language. What a compound expression featuring non-standard runtime items evaluates to is implementation specific.

An item evaluates to itself.

Compound expressions evaluate according to the following rules (a and b represents any integer item (not an operator), c and d represent any item). Also, the left is always evaluated first, then the middle, then the right.

(a + b) Evaluates to a plus b. Overflow returns +. (0 + b) always evaluates to b, even if b is not a number. If a is not zero and b is a non-numerical item, or if a is a non-numerical item, it returns -.
(a - b) Evaluates to a minus b. Underflow returns +. If a or b are non-numerical, it returns -
(a * b) Evaluates to a multiplied by b. Overflow returns +. If a or b are non-numerical, it returns -
(a / b) Evaluates to a divided by b, rounded down. Division by zero returns +. If a or b are non-numerical, it returns -
(a @ c) Evaluates to c. Also has the side effect of setting a to c in a hashtable of numbers to items. An operator on the left has special semantics.
(c = d) Evaluates to 1 if c and d are equal, zero otherwise.
(a ! c) Evaluates to the element in the hashtable set by @ with the key of a. C is ignored. If a is an operator, there are some special semantics, which might not ignore c.
(c ? d) If c is not zero, evaluates to (d ! 1), otherwise evaluates to ((d + 1) ! 1). This can be achieved with loops, but is really complicated.
(c a d) Compound expressions where the middle expression evaluates to a number are extension points. Five-digit numbers (10000-99999) are reserved for official extensions.

Special semantics

If the operator on the left is +, it does I/O. Setting it to a number outputs the number it is set to, while getting its value inputs a number and assigns it to the item on the right of the !, and also returns it, including special semantics. While it starts out with numerical I/O, setting it to / sets it to byte-by-byte if it's currently numerical, Unicode I/O if it's currently byte-by-byte, and numerical if it's currently Unicode.

If the operator on the left is - it does a loop. Every time you assign to it, it adds the item to a list of tokens, where an item represents itself, except if it is 15001500, which represents an opening parenthesis, or 30003000 which represents a closing parenthesis. These numbers can still be obtained during the loop's runtime, but can't be literal (the easiest way is probably just math). If the first thing assigned to it since the start of the program or the most recent loop start is 15001500 it will continue adding until it is matched, otherwise the loop expression is a single item, which is useless and either loops infinitely or doesn't start, and tries to run immediately. Once the expression is fully created, it evaluates it over and over again until (1 ! 0) evaluates to 0 at the start of a loop iteration (which could be immediately true, meaning the loop would never run and be discarded). The loop evaluates to the final evaluation of the last iteration, or + if the loop never ran.

If the operator on the left is * it operates on the stack of a variable. If it is a @ operation, it pushes the current value of the variable specified by the right side to its stack. If it is a ! operation, it pops a value and returns it, so that (a @ (* ! a)) retrieves it into the variable (if the stack is empty, it returns +, though that could also be a value on the stack).

Strategies

A way to nullify an expression e and return f can be (0 (e / 0) f). This is because (anything / 0) evaluates to + as an error condition, and (0 + b) always evaluates to b.

While dividing by zero returns + and not zero, you can still get numeric booleans.

not: (1 - a)
and: (a * b)
or:  ((((a + b) / (a + b)) = +) = 0)


Examples

Hello world!

Also politely follows with a newline.

(((((((((((((((((((((((((((+ @ /) / 0) @ 72) / 0) @ 101) / 0) @ 108) / 0) @ 108) / 0) @ 111) / 0) @ 32) / 0) @ 119) / 0) @ 111) / 0) @ 114) / 0) @ 108) / 0) @ 100) / 0) @ 33) / 0) @ 10)

Truth-machine

(0 (((0 (((0 (((0 (((0 (((0 ((+ ! 1) / 0) -) @ 15001500) / 0) -) @ +) / 0) -) @ @) / 0) -) @ 1) / 0) -) @ 30003000) / 0) (+ @ 0))