Stlang

Stlang is a stack-based esoteric programming language invented by User:Feuermonster in 2012. The main idea is to create a stack-based esoteric language with a very sophisticated standard library which outshines other major languages' standard libraries. Also, due to possible use in golfing, often-used function names must have a short, symbolic alias. Stlang supports anonymous functions. But most importantly: The spirit of Stlang is to implement lots of features in very weird and esoteric ways no other language or sane person would implement them with.
== Builtin functions ==
Note: Since Stlang is stack based, "return" means "push the result on to the stack". This also applies to things like "removes element from list", etc.
Function	Alias 	Parameters 	Description
add 	a, b 	Returns a + b 	
sub 	 	 	
a, b 	Returns a - b	 	
mul 	*= 	a, b 	Returns a * b
div 	/ or // 	a, b 	Returns a / b
map 	m 	fn, ls 	Applies the function pointed to by fn to each element in ls and collects the return values in a list.
dup 	a 	Duplicates the top-most element of the stack	
swp 	<> 	a,b 	Swaps the two top-most elements of the stack
flz 	 	n 	Creates a list with n zero elements
red 	r 	fn, ls 	Applies the function pointed to by fn to the first two elements of ls, stores the result, and applies the function to this last result and the next element in ls.
app 	: 	ls, e 	Appends the element e to the list ls.
sum 	/S 	ls 	Returns the sum of all elements in ls.
prd 	/P 	ls 	Returns the product of all elements in ls.
sqrt 	/v 	a 	Returns the square-root of a.
len 	l 	ls 	Returns the length of ls.
nub 	n 	ls 	Removes all duplicate elements from ls.
rev 	<- 	ls 	Reverses ls.
ls 	[] 	 	Returns an empty list.
fac 	! 	a 	Returns the factorial of a
pow 	** or /* 	a,b 	Returns a ** b
ln 	 	a 	Returns the natural logarithm of a
log 	 	a 	Returns the 10-logarithm of a
e 	 	 	Returns the number e
pi 	 	 	Returns the number pi
sin 	 	a 	Returns sin(a)
sinh 	 	a 	Returns sinh(a)
asin 	 	a 	Returns asin(a)
asinh 	 	a 	Returns asinh(a)
cos 	 	a 	Returns cos(a)
cosh 	 	a 	Returns cosh(a)
acos 	 	a 	Returns acos(a)
acosh 	 	a 	Returns acosh(a)
tan 	 	a 	Returns tan(a)
tanh 	 	a 	Returns tanh(a)
atan 	 	a 	Returns atan(a)
atanh 	 	a 	Returns atanh(a)
flr 	 	a 	Returns floor(a)
ceil 	 	a 	Returns ceil(a)
deg 	 	a 	Converts from radians to degrees.
rad 	 	a 	Converts from degrees to radians.
head 	;h 	ls 	Returns the first element of ls.
tail 	;t 	ls 	Returns all but the first element of ls.
last 	;l 	ls 	Returns the last element of ls.
init 	;i 	ls 	Returns all but the last element of ls.
pair 	(,) or (, 	a,b 	Returns the pair (a,b)
zipWith 	<,> or ;Z 	fn,as,bs 	Zips the lists as and bs using the function fn. (Google zip if you do not know what zipping lists means).
unzip 	ls 	>,< or ;U 	Counterpart of zip. Undoes what {pair} zipWith would do. Returns a pair of lists.
take 	n, ls 	;< 	Returns the first n elements of ls.
drop 	n, ls 	;> 	Removes the first n element of ls.
unfinished. More documentation is coming, of course.
== Details ==
As mentioned: Stlang is stack based. Everything which is not a function call is pushed on to the stack. Functions then
take values from the stack, do their stuff, and push the result back on to the stack.
Stlang also supports anonymous functions (lambdas) with the {}-Notation. {5 add} is an anonymous function which obviously adds 5. What Stlang does with anonymous functions is, it creates a new standalone function with a random name for that anonymous function and replaces the anonymous function inside the code with a call to this randomly named function. There are functions to actually access the name of the created function (me is replaced with the name of the current anonymous function, and parent or ^- is replaced with the name of the parent anonymous function) but these are considered to be especially esoteric ;).
Stlang also performs a little optimization. Let's see an example:
<nowiki>
fn myRange
 []{<> ++ 0 >{1 - ++ -3 ^^ <> : ^-}{$ <-}?};
efn
fn main
 10 myRange
efn</nowiki>
is converted to
<nowiki>
fn 9C36B5A81FG724E0
 <> ++ 0 > '94C7BF2518E03DA6 'GB1C6785D3024FA9 ? 
efn
fn myRange
 [] '9C36B5A81FG724E0 ; 
efn
fn main
 10 myRange 
efn
fn GB1C6785D3024FA9
 $ <- 
efn
fn 94C7BF2518E03DA6
 1 - ++ -3 ^^ <> : 9C36B5A81FG724E0 
efn</nowiki>
These weird function names are the anonymous functions. This is further optimized through inlining to
<nowiki>
fn main
 10 [] <> ++ 0 > '94C7BF2518E03DA6 'GB1C6785D3024FA9 ? 
efn
fn GB1C6785D3024FA9
 $ <- 
efn
fn 94C7BF2518E03DA6
 1 - ++ -3 ^^ <> : <> ++ 0 > '94C7BF2518E03DA6 'GB1C6785D3024FA9 ? 
efn
</nowiki>
And that's about it ;)
== Hello, World! ==
The following code demonstrates various ways to achieve the goal of greeting the world.
<nowiki>
fn main
 way1 way2 way3
 way4 way5 way6
efn
fn way1
 'Hello, \s + 'World! + @
efn
fn way2
 'Hello, <o \s <o 'World! <o \n <o
efn
fn way3
 \n 'World! \s 'Hello, <o <o <o <o
efn
fn way4
 {<o} [] 'Hello, : \s : 'World! : \n : m
efn
fn way5
 [] 'Hello, : \s : 'World! : _ @
efn
fn way6
 [] 'Hello, : \s : 'World! : \n : <- # <o <o <o <o
efn
</nowiki>
== Syntax ==
A function is declared by fn followed by a space and the name of the function. A function declaration is terminated by efn.
Normal functions can not be nested. Anonymous function are declared between { and }. Anonymous functions can
be nested. A function can be referenced by ' followed by the name of the function. When a program is launched, its main method is executed. Function calls
and values are usually separated by spaces (if not in golfing mode).
=== Comments ===
There are no real comments, but we still can write comments like this:
<nowiki>
fn comment
 {This is a comment, but it's actually just code which is never executed} $
 doStuff
efn
</nowiki>
=== Strings ===
There are no real strings, but it is possible to abuse that function references are implemented as strings therefore
<nowiki>
fn \o/
 'String <0
efn
</nowiki>
will output String to standard out. I think it is obvious that this may have some esoteric side effects if you are careful.
<nowiki>
fn \o/
 'String ++ ; <0
efn
fn String
 0 $
efn
</nowiki>
This will call the function String and then output String.
=== Variables ===
There are no real variables (you should know this sentence by now ;)), but it is possible to create functions on the fly. The following examples demonstrates 
this by creating a function test on the fly and call it:
<nowiki>
fn main
 'test [] Hello : '@ : ^F test 
efn
</nowiki>
This can be used for storing values as the following code demonstrates:
<nowiki>
fn main
 {Initialize myGlobalVar with the value 1336. 
 Remember: Code is string -> We have to store 1336 as string. 
 We use (i to convert the float to int, as per default all numbers are floats.
 } $
 'myGlobalVar [] '1336 : '(i : ^F
 myGlobalVar @ {This will print 1336}$
 doSomething
 myGlobalVar @ {Somehow myGlobalVar was magically incremented ;)}$
efn
fn doSomething
 {Load myGlobalVar add 1 to it and store it back again} $
 myGlobalVar .1+(s[]<>: '(i : 'myGlobalVar <> ^F
efn
</nowiki>
=== Pattern matching ===
Stlang also supports something like pattern matching. Functions can match against the top-most element of the stack.
The pattern to match is followed by the name of the function and a :. Here is an example:
<nowiki>
fn main
 0 isZero @
efn
fn isZero
 ?0
efn
fn isZero:0
 ?1
efn
fn isZero:0.0
 ?1
efn
</nowiki>
Another example:
<nowiki>
fn main
 'John checkName
 'Lisa checkName
 'Dylan checkName
efn
fn checkName
 'I \s + 'don't + \s + 'know + \s + <> + @
efn
fn checkName:John
 'I \s + 'like + \s + <> + @
efn
fn checkName:Dylan
 'I \s + 'hate + \s + <> + @
efn
</nowiki>
which produces the following output:
I like John
I don't know Lisa
I hate Dylan
=== Golfing ===
There is a special golfing mode for a sequence of function calls. This mode is entered with a dot (.) and left with a space.
This 11 characters long program reads lines in an infinite loop from the console and reverses them.
<nowiki>
M ./r<-` \
</nowiki>
Without the golfing mode this program has to be written as:
<nowiki>
M /r <- ` \
</nowiki>
In clear code the same program is:
<nowiki>
fn main
 readln rev show main
efn
</nowiki>
=== OOP ===
Stlang also supports some sort of object oriented programming. Classes can be defined as well as some sort of inheritance. Classes can inherit from multiple classes
and from each other.
==== Classes ====
<nowiki>
class Animal
 fn makeSound
 &sound show
 efn
 prop sound 'Miau
eclass
fn main
 'Animal new makeSound
 'sound 'Woof modprop makeSound
efn
</nowiki>
In this example a class named Animal is defined and an object of that class is created in main by the new function. modprop is a function to modify properties.
Properties can be accessed through & followed by the name of the property. 
==== Casts and Inheritance ====
<nowiki>
class Person
 fn greet
 'Hello, out space out &Name show
 efn
 prop Name 'Peter
eclass
class Manager
 fn greet
 'Greetings, out space out &Name show
 efn
eclass
inherit Manager Person
fn main
 'Person new greet pop
 'Manager new greet pop
 'Manager new 'Name 'John modprop greet
 'Person castTo greet pop
efn
</nowiki>
Objects of classes can be casted to other classes with the castTo function. Any class can be casted to any other class!
<nowiki>
class Foo
 fn do
 'Foo show
 efn
eclass
class Bar
 fn do
 'Bar show
 efn 
eclass
class Baz
 fn foobar
 'Baz show
 efn
eclass
class Buz
eclass
inherit Buz Baz
inherit Buz Bar
class A
 fn a
 'A show
 efn
eclass
class B
 fn b
 'B show
 efn
eclass
inherit A B
inherit B A
fn main
 'Foo new 'Bar castTo do pop
 'Buz new foobar do 'Foo castTo do pop
 'A new a b pop
 'B new a b pop
efn
</nowiki>
Classes can inherit from multiple classes and even a class A can inherit from B and B can inherit from A.
<nowiki>
class Tester
 fn addTest
 pop add
 efn
 fn saySomething
 'something show
 efn
eclass
fn main
 'Tester new
 saySomething
 5 6 that addTest swp show saySomething
efn
</nowiki>
The that function can be used to get the latest object back on top of the stack (no matter where on the stack it is). This is sometimes necessary if you want to pass parameters to a member function.
==== Constructors/Destructors ====
Classes can implement the functions "con" (constructor) and "decon" (deconstructor) which are called automatically on object construction or deconstruction.
==== Internals ====
An object is somehow an instance of a class. A class holds function definitions and properties with their default value. The new function creates an object
based on its class definition and pushes that object on to the stack. If a function is called which is neither a builtin function nor a function defined in the
global scope Stlang checks if the topmost value on the stack is an object and if it is, it calls the function of the corresponding class. After a call to a member function the topmost value of the stack is always the object. Property accessing works analog to this. To access a property of an object that object must be on top.
== Examples ==
=== Truth-machine ===
==== Clear-text version ====
<nowiki>
fn main
 readln toint 1 eq
 {
 { pop
 false }
 { 1 toint show }
 0 until
 }
 {
 0 toint show
 }
 cif
efn
</nowiki>
==== Golfed version ====
<nowiki>
M ./r(i1=={{.$?0}{.1(i@}.0U}{.0(i@}? \
</nowiki>
==== OOP version ====
<nowiki>
class 0
 fn con
 0 toint show
 efn
eclass
class 1
 fn con
 { pop false } { 1 toint show } 0 until
 efn
eclass
fn main
 readln new
efn
</nowiki>
===== Golfed OOP version =====
<nowiki>
Cc 0 fn con .0(i@ \ cC
Cc 1 fn con{.$?0}{.1(i@}.0U \ cC
M ./rN \
</nowiki>
=== 99 bottles of beer ===
<nowiki>
fn main
 99 (i) strophe
efn
fn strophe
 <+ '_bottles_of_beer_on_the_wall, '_ .\s/R<><o@
 <+ '_bottles_of_beer. '_ .\s/R<><o@
 'Take_one_down,_pass_it_around, '_ .\s/R@
 .1-(i<+ '_bottles_of_beer_on_the_wall. '_ .\s/R<><o@
 \n <o strophe
efn
fn strophe:1
 <+ '_bottle_of_beer_on_the_wall, '_ .\s/R<><o@
 <+ '_bottle_of_beer. '_ .\s/R<><o@
 'Take_one_down,_pass_it_around, '_ .\s/R@
 $ 'No_more_bottles_of_beer_on_the_wall. '_ .\s/R@
efn
</nowiki>
=== Others ===
Find the first number 2^n greater than 100:
<nowiki>
fn \o/{100 >}{2 *}2 -> @ efn
</nowiki>
Read comma seperated values from the console and print the sum of all numbers (infinite loop):
<nowiki>
fn \o/{+}{(i)}/r ', ;; m r @ \o/ efn
</nowiki>
Print the 11th fibonacci number:
<nowiki>
M 11 fib @ \
fn fib .<+1-"<>2-"+ \
fn fib:0.0 \
fn fib:1.0 \
</nowiki>
Print the 11th fibonacci number in clear, commented, well formated code:
<nowiki>
fn main
 11 fib show
efn
fn fib
 {fib n = (fib (n-1)) + (fib (n-2))} pop
 dup 
 1 sub fib 
 swp
 2 sub fib
 add
efn
fn fib:0.0
 {fib 0 = 0} pop
efn
fn fib:1.0
 {fib 1 = 1} pop
efn
</nowiki>
== Implementation ==
Not available anymore.
=== Problems ===
* Ugly code (of course)
* evalFn is recursive so the max recursion depth is reached very fast (in that case, python does not terminate but yield the weirdest results ;))
Category:Implemented 
Category:Languages
Category:Stack-based
Category:Object-oriented paradigm
Category:2012
Category:Turing complete
Category:High-level