Selt

Selt is a self-modifying esoteric programming language created by User:Zip.
== Structure ==
Each Selt program consists of a series of commands and labels; each line has one of each. Labels and commands are seperated by colons (:). If a line contains no label, then the label of that line is the empty string by default.
== Labels ==
Labels can contain any character except a colon. Additionally, any whitespace (tabs or spaces) before a label name is ignored. A label can be repeated on multiple lines, however this will result in only the first instance of the label being accessible.
== Commands ==
A command consists of a series of terms and operators. A term is any sequence of characters, and may be broken by operators or spaces. In order to prevent a term being broken up, a backslash (\) may be used to escape a character. Each command contains an instruction (which is just a term at the beginning of the command). Each instruction takes a certain number of operands, which may be either terms or expressions. Expressions are combinations of terms and operators, which denote a calculation to perform at runtime. Expressions and terms are fully interchangeable.
=== Instructions ===
Form 	Name 	Description
print [expr] 	Print 	Prints the value of [expr]
println [expr] 	Print Line	Prints the value of [expr], followed by a newline (U+000A)
goto [expr] 	Goto 	Jumps execution to the label named the value of the expression. If the label does not exist, an error message is given and execution is halted.
call [expr] 	Call 	Calls a subroutine at a label. A return instruction may be used to return back to the previous call.
return 	Return 	Returns back to the previously ran call instruction. If no call instructions were executed previously, then execution halts.
[expr A] = [expr B]	Assignment	Sets the value at the label [expr A] to [expr B]
=== Binary Operators ===
Binary operators take two arguments; one on the left, and one on the right.
Operator 	Name 	Description
Add 	Interprets both arguments as integers, adds them, and returns the result. If either side can not be interpreted as an integer, then an error will be thrown an execution will halt. (This is true of all arithmetic operations (Those being + - / * %))	
Subtract 	Interprets both arguments as integers, subtracts them, and returns the result. 	
* 	Multiply 	Interprets both arguments as integers, multiplies them, and returns the result.
/ 	Divide 	Interprets both arguments as integers, divides them, and returns the result.
% 	Multiply 	Interprets both arguments as integers, modulos them, and returns the result.
~ 	Concatenate 	Concatenates the value of both arguments.
. 	Index 	Takes the second argument, and takes that index of the first argument. If the index is out of bounds, then an error is given and execution halts.
== 	Equals 	Returns 1 if both sides are equal, 0 if not.
!= 	Not Equals 	Reverse of equals
> 	Greater Than 	Interprets both arguments as integers, then returns 1 if the left side is greater than the right side, otherwise returns 0. If either side can not be interpreted as an integer, then an error is given and execution halts. (This is true of all comparison operators (those being > < >= <=))
< 	Less Than 	Interprets both arguments as integers, then returns 1 if the left side is less than the right side, otherwise returns 0.
>= 	Greater Than or Equal 	Interprets both arguments as integers, then returns 1 if the left side is greater than or equal to the right side, otherwise returns 0.
<= 	Less Than or Equal 	Interprets both arguments as integers, then returns 1 if the left side is lesser than or equal to the right side, otherwise returns 0.
&& 	And 	Returns 1 only if both sides are 1, and 0 otherwise. (Note that this is not a short-circuit operator; it will always evaluate both sides.)
||	Or 	Returns 1 only if both sides are 1, 0 otherwise. (Likewise, this is not a short-circuit operator.)
=== Unary Operators ===
Unary operators only take one argument, placed to the right of the operator
Operator	Name 	Description
! 	Not 	If the argument is 1, returns 0, otherwise returns 1.
@ 	At 	Returns the value at a label. If the label does not exist, execution halts and an error is thrown. (likewise with &#amp;)
& 	Line 	Gets the line of a label.
| 	Deline	Gets the text at a given line. (not including the label at that line.)
? 	Length	Returns the length of the argument.
=== Operator Precedence ===
Below is a table of operator precedence. A higher precedence means that an expression utilizing that operator will be evaluated before a neighboring expression. If two operators have the same precedence, then they're evaluated left-to-right.
Operator(s) 	Precedence
@ & | ! . ? 	7
|| 	6
&& 	5
== != < <= > >=	4
* / % 	3
2 	
~ 	1
=== Miscellaneous ===
* The label stdin is special; when you try to read a value from that label it reads a line from standard input (no trailing newline is added.)
* The grave symbol (`) is used to represent an empty string. This can be escaped with a backslash like any other character.
== Programming in Selt ==
Selt is a self-modifying language, that is when you run a selt program, the code itself is being modified as it runs. The assignment instruction doesn't assign variables, it assigns labels. This means that in order to store a value, you store it in the code itself. To see what I mean, consider the following code:
x:
x = 5
println @x
The first line contains a label called x. There is no instruction on this label, so nothing happens when this line is read. On the next line, we read x = 5. This sets the value at the label x to 5. One very important thing to note is that since all that is being done is manipulating text, all values are a string. We then run println @x, which gets the value at the label x and prints it. In theory, we could jump back to the label x and run it as code, however that would just cause an error.
=== Escaping ===
You have to escape characters a lot in Selt. This is because strings are not quoted; since it's the only datatype in Selt it would just get overly annoying to do. Instead, if you want a space or a reserved operator in Selt, you just escape it with a backslash. To demonstrate, here's the Hello, World! program in Selt:
println Hello,\ World\!
You can see there's a few backslashes in there. The first backslash is to escape a space. If that one wasn't there, then this would be interpreted as two terms following one another, which is not what we want (and would cause an error). The next backslash is to escape the ! operator, which would otherwise be interpreted as, well, an operator, and not as part of our string.
=== Loops ===
Loops can be done using the goto command. So, let's say you want to repeatedly increment a number and print it out. That program could be achieved by the following code:
goto loop
n:0
loop:n = @n+1
 goto loop
Note the goto loop at the start. This makes sure that we skip over the code after it, because if that got executed, it would give an error (since 0 is not a valid command). In the loop, we assign the label n to @n+1. This takes the value at the label n and adds one to it.
=== Conditionals ===
You may notice that Selt does not have a conditional instruction. However, what selt does have is conditional operators. And, since Selt has the concatenation operator and allows you to goto an expression, you can use this to jump to one label if a condition is false, and another if a condition is true. Here's a following program that detects if the user typed "Hello" or not:
goto say~(@stdin == Hello)
say0:println You\ did\ not\ type\ hello
return
say1:println You\ did\ type\ hello
Note the return at line 3. This makes sure that execution does not continue down to say1 by halting the program. Now, with conditionals and loops, we can create a Truth Machine in Selt:
goto loop~(@stdin == 1)
loop1:print 1
goto loop1
loop0:print 0
== Examples ==
The following is a list of example programs in Selt
=== 99 bottles of beer ===
# https://esolangs.org/wiki/99_bottles_of_beer
loop:
 println @bottles~\ bottles\ of\ beer\ on\ the\ wall,
 println @bottles~\ bottles\ of\ beer\.
 println Take\ one\ down,\ pass\ it\ around,
 bottles = @bottles-1
 goto cont~(@bottles > 1)
 cont1:println @bottles~\ bottles\ of\ beer\ on\ the\ wall\.
 println `
 goto loop
cont0:
 println 1\ bottle\ of\ beer\ on\ the\ wall\.
 println `
 println 1\ bottle\ of\ beer\ on\ the\ wall,
 println 1\ bottle\ of\ beer\.
 println Take\ one\ down,\ pass\ it\ around,
 println No\ more\ bottles\ of\ beer\ on\ the\ wall\.
return
bottles:99
=== Alphabet ===
Takes an index, and returns that letter of the alphabet (0-indexed)
# given a number, this prints that letter of the alphabet (zero-indexed)
goto start
alphabet:a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
start:println |(&alphabet+@stdin)
=== Cat by Char ===
A simple program to demonstrate looping through a string
# prints out the input char by char
var = @stdin
loop1:
 print @var.@index
 index = @index+1
 goto loop~(@index < ?@var)
loop0: return
var:
index:0
=== Cat ===
# prints its input
start:println @stdin
goto start
=== Deadfish Interpreter ===
# https://esolangs.org/wiki/Deadfish
loop:
 print \>\>\ 
 input = @stdin
 index = 0
 goto inloop~(@input != `) # jump to end when input is empty
 inloop1:
 goto @input.@index # go to the label corresponding to each command
 i:val = @val+1
 goto end
 d:val = @val-1
 goto end
 s:val = @val*@val
 goto end
 o:println @val
 goto end
 end:goto reset~((@val == \-1) || (@val == 256))
 reset1:val = 0
 reset0:
 index = @index+1
 goto inloop~(@index < ?@input)
 inloop0: goto loop
index:0
val:0
input:
=== Code Editor ===
# a simple program that lets you edit and execute selt code
goto start
index:
line:
# changeable, just add more lines to the end of the program
lines:20
start:print \?
goto @stdin
edit:
 println Line
 line = @stdin
 println Text
 code~@line = @stdin
 goto start
view:
 index = 0
 viewloop0:
 println @(code~@index)
 index = @index+1
 goto viewloop~(@index >= @lines)
 viewloop1:goto start
run:
code0:
code1:
code2:
code3:
code4:
code5:
code6:
code7:
code8:
code9:
code10:
code11:
code12:
code13:
code14:
code15:
code16:
code17:
code18:
code19:
=== Hello, World! ===
# prints Hello, World!
println Hello,\ World\!
=== Quine ===
print |1
=== Truth Machine ===
# takes input, if 0 it prints 0 and halts. if 1, it prints 1 indefinitely
goto branch~@stdin
branch1:print 1
goto branch1
branch0:print 0
=== Brainfuck Interpreter ===
loop:
 print BF\>\ 
 code = @stdin
 goto end~(@code == `)
 end0:
 ip = 0
 execloop1:
 goto i~(@code.@ip)
 i+:tape~@ptr = @(tape~@ptr)+1
 goto execend
 i-:tape~@ptr = @(tape~@ptr)-1
 goto execend
 i>:ptr = @ptr+1
 goto execend
 i<:ptr = @ptr-1
 goto execend
 i.:goto ch~((@(tape~@ptr)) == 10)
 ch1: println `
 goto execend
 ch0: print @ascii.(@(tape~@ptr))
 goto execend
 i[:goto lbrack~(@(tape~@ptr) == 0)
 lbrack1:
 brack = 1
 lbrack_loop1:
 ip = @ip+1
 goto lbrack_~(@code.@ip)
 lbrack_[: brack = @brack+1
 goto lbrack_\+
 lbrack_]: brack = @brack-1
 lbrack_+:
 lbrack_-:
 lbrack_>:
 lbrack_<:
 lbrack_.:
 lbrack_,:goto lbrack_loop~(@brack > 0)
 lbrack_loop0: goto execend
 i]:goto rbrack~(@(tape~@ptr) != 0)
 rbrack1:
 brack = 1
 rbrack_loop1:
 ip = @ip-1
 goto rbrack_~(@code.@ip)
 rbrack_[: brack = @brack-1
 goto rbrack_\+
 rbrack_]: brack = @brack+1
 rbrack_+:
 rbrack_-:
 rbrack_>:
 rbrack_<:
 rbrack_.:
 rbrack_,:goto rbrack_loop~(@brack > 0)
 rbrack_loop0: goto execend
 lbrack0:
 rbrack0:
 execend:
 ip = @ip+1
 goto execloop~(@ip < ?@code)
 execloop0:
 println `
 end1:
 goto loop
code:
ip:
brack:
ptr:0
ascii: 	 !"#$%&'()*+,-./0123456789 ;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 
tape0:0
tape1:0
tape2:0
tape3:0
tape4:0
tape5:0
tape6:0
tape7:0
tape8:0
tape9:0
tape10:0
tape11:0
tape12:0
tape13:0
tape14:0
tape15:0
tape16:0
tape17:0
tape18:0
tape19:0
tape20:0
tape21:0
tape22:0
tape23:0
tape24:0
tape25:0
tape26:0
tape27:0
tape28:0
tape29:0
tape30:0
tape31:0
== Interpreter ==
The official interpreter for Selt is available Here, and is also packaged in DELIC
Category:Languages Category:Self-modifying Category:2022 Category:Turing complete Category:Implemented