1337

1337 is a language by User:Olsner based on single-combinator combinatory logic and a simple precedence parser, with the set of integers (or, really, any ordered set of items) as its input alphabet. The language has a single operator, function application, that can be used with any precedence specified by the input integer. The single combinator used is Fokker's X combinator,, with the standard S combinator.

The language name also makes a very good excuse for calling things relating to this language "1337", as demonstrated by the contents of this page.

For example, the program  represents the expression. Since all non-operator parts of the input program would be the symbol representing the X combinator, those symbols are elided from the source and implicitly inserted by the parser. In order to understand the example, we insert the X's again, at the end and the beginning and between every operator. The program can now be seen as, where  stands for function application with precedence n - the function application with the lower number binding harder. Reapplying parantheses and rewriting to more familiar syntax, we get  =   =.

Example
This program calculates and prints all prime numbers. This is translated from the prime number sample program from the Lazy K home page.

[1,32,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,31,1,0,30,1,29,1,0,28,1,0,27,1,26 ,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,25,1,0,24,1,0,3,1,2,1,0,23,1,0,5,1,4,1 ,0,3,1,2,1,0,22,1,0,9,1,8,1,0,7,1,0,3,1,2,1,0,6,1,0,2,1,0,5,1,0,4,1,0,3 ,1,2,1,0,3,1,5,1,2,1,21,1,0,20,1,0,3,1,2,1,0,19,1,0,3,1,2,1,18,1,0,3,1, 2,1,0,17,1,0,10,1,0,3,1,2,1,0,9,1,0,3,1,2,1,8,1,0,3,1,2,1,0,7,1,0,6,1,0 ,3,1,2,1,0,5,1,0,3,1,2,1,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,6,1,4,1,0,3, 1,0,2,1,2,1,3,1,2,1,16,1,15,1,0,14,1,13,1,0,12,1,0,3,1,2,1,0,11,1,0,5,1 ,4,1,0,3,1,0,2,1,2,1,10,1,0,3,1,2,1,9,1,0,8,1,7,1,0,4,1,0,3,1,2,1,0,3,1 ,5,1,0,4,1,0,3,1,2,1,0,3,1,4,1,0,2,1,2,1,6,1,0,4,1,0,3,1,0,2,1,2,1,3,1, 0,2,1,2,1,4,1,0,2,1,2,1,5,1,0,4,1,0,3,1,2,1,0,3,1,4,1,0,2,1,2,1,5,1,0,4 ,1,0,3,1,2,1,0,3,1,8,1,0,3,1,0,2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,14,1,0,3,1 ,2,1,3,1,20,1,19,1,0,3,1,2,1,18,1,0,17,1,0,3,1,0,2,1,2,1,16,1,15,1,0,14 ,1,0,13,1,0,12,1,0,7,1,0,2,1,0,2,1,6,1,0,3,1,0,2,1,2,1,5,1,4,1,3,1,0,2, 1,2,1,11,1,10,1,0,4,1,0,3,1,2,1,0,3,1,4,1,0,2,1,2,1,6,1,0,4,1,0,3,1,2,1 ,0,3,1,5,1,0,4,1,0,3,1,2,1,0,3,1,4,1,0,2,1,2,1,9,1,0,8,1,7,1,0,6,1,0,3, 1,0,2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,8,1,9,1,2,1,12,1,2,1,13,1,0,10,1,0,3, 1,2,1,0,9,1,0,5,1,4,1,0,3,1,0,2,1,2,1,8,1,0,3,1,2,1,7,1,0,6,1,5,1,0,4,1 ,0,3,1,2,1,0,3,1,6,1,0,3,1,0,2,1,2,1,3,1,2,1,10,1,5,1,4,1,3,1,0,2,1,2,1 ,14,1,0,7,1,0,3,1,2,1,0,6,1,0,5,1,4,1,0,3,1,0,2,1,2,1,5,1,0,2,1,0,4,1,0 ,3,1,0,2,1,2,1,4,1,2,1,8,1,0,3,1,2,1,7,1,0,6,1,5,1,0,4,1,0,3,1,2,1,0,3, 1,6,1,0,3,1,0,2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,17,1,5,1,4,1,3,1,0,2,1,2,1, 24,1,4,1,3,1,0,2,1,2,1,27,1,0,3,1,0,2,1,2,1,3,1,2,1,30,1,0,15,1,14,1,0, 13,1,12,1,0,11,1,10,1,0,9,1,0,3,1,0,2,1,2,1,8,1,7,1,0,6,1,5,1,0,4,1,0,3 ,1,2,1,0,3,1,4,1,0,2,1,2,1,6,1,0,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,4,1, 0,2,1,2,1,5,1,0,4,1,0,3,1,2,1,0,3,1,4,1,0,2,1,2,1,11,1,15,1,0,6,1,0,3,1 ,2,1,0,5,1,0,3,1,2,1,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,7,1,6,1,0,3,1,0, 2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,31,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,28,1,0 ,15,1,14,1,0,13,1,0,3,1,2,1,0,12,1,0,7,1,6,1,0,5,1,0,4,1,0,3,1,0,2,1,2, 1,3,1,2,1,4,1,3,1,0,2,1,2,1,11,1,0,2,1,0,10,1,0,9,1,0,3,1,2,1,0,8,1,0,3 ,1,2,1,7,1,0,3,1,2,1,0,6,1,0,5,1,4,1,0,3,1,0,2,1,2,1,5,1,10,1,2,1,27,1, 0,10,1,0,3,1,2,1,0,9,1,0,5,1,4,1,0,3,1,2,1,0,8,1,0,5,1,4,1,0,3,1,2,1,7, 1,0,6,1,0,3,1,2,1,0,5,1,0,3,1,2,1,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,6,1 ,5,1,0,4,1,0,3,1,2,1,0,3,1,26,1,25,1,0,24,1,0,3,1,2,1,0,23,1,0,7,1,6,1, 0,5,1,0,4,1,0,3,1,0,2,1,2,1,3,1,2,1,4,1,3,1,0,2,1,2,1,22,1,0,3,1,2,1,21 ,1,0,20,1,19,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,18,1,0,17,1,16,1,0,15,1,0, 3,1,2,1,0,14,1,0,13,1,12,1,0,11,1,10,1,0,9,1,0,3,1,2,1,0,8,1,0,3,1,2,1, 7,1,0,3,1,2,1,0,6,1,0,5,1,4,1,0,3,1,0,2,1,2,1,5,1,9,1,2,1,13,1,0,8,1,0, 3,1,2,1,0,7,1,0,3,1,2,1,6,1,0,5,1,4,1,0,3,1,0,2,1,2,1,3,1,2,1,5,1,0,3,1 ,0,2,1,2,1,3,1,2,1,8,1,4,1,0,3,1,0,2,1,2,1,3,1,2,1,17,1,0,11,1,0,3,1,2, 1,0,10,1,0,5,1,4,1,0,3,1,2,1,0,9,1,0,5,1,4,1,0,3,1,2,1,8,1,0,6,1,0,3,1, 2,1,0,5,1,0,3,1,2,1,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,7,1,6,1,0,3,1,0,2 ,1,2,1,5,1,4,1,3,1,0,2,1,2,1,11,1,7,1,6,1,0,3,1,0,2,1,2,1,5,1,4,1,3,1,0 ,2,1,2,1,20,1,0,5,1,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,15,1,0,9,1,8,1,0, 7,1,6,1,0,3,1,0,2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,14,1,0,13,1,0,3,1,2,1,0, 12,1,0,3,1,2,1,11,1,0,3,1,0,2,1,2,1,10,1,9,1,0,8,1,7,1,0,6,1,0,3,1,0,2, 1,2,1,5,1,4,1,3,1,0,2,1,2,1,8,1,13,1,7,1,0,6,1,5,1,0,4,1,0,3,1,0,2,1,2, 1,3,1,2,1,6,1,0,3,1,2,1,4,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,24,1,6,1,0,3, 1,0,2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,28,1,0,4,1,0,3,1,2,1,0,3,1,4,1,0,2,1, 2,1,28,1,0,3,1,0,2,1,2,1,3,1,0,2,1,2,1,11,1,0,10,1,9,1,0,8,1,7,1,0,6,1, 0,3,1,0,2,1,2,1,5,1,4,1,3,1,0,2,1,2,1,8,1,10,1,0,3,1,0,2,1,2,1,3,1,0,2, 1,2,1]

Construction of 1337 programs
A simple haskell function to convert SK-programs to 1337 programs:

data SkExp = CombS | CombK | SkApp SkExp SkExp skToNum CombS = [1,0] -- (x x) x skToNum CombK = [0] -- (x x) skToNum (SkApp x y) = xs++[n]++ys where xs = skToNum x 		ys = skToNum y 		n = max (maximum xs) (maximum ys + 1)

Parser
The basis of the interpreter is a simple lambda calculus, based on the following data type, which is produced directly by the parser.

data LambdaExp = Lambda Id LambdaExp | App LambdaExp LambdaExp | Var Id 	deriving (Eq,Show) type Id = Int

Here is the X combinator used, (\f -> f s (\x _ _ -> x)), expressed as a LambdaExp.

sComb = Lambda 0 $ Lambda 1 $ Lambda 2 $ App (App (Var 0) (Var 2)) (App (Var 1) (Var 2)) xComb = Lambda 0 $ App (App (Var 0) sComb) (Lambda 0 $ Lambda 1 $ Lambda 2 $ Var 0)

And here is the parser, using the *** operator from the Control.Arrow module and otherwise only functions from the standard Prelude.

parse :: Ord a => [a] -> LambdaExp parse xs = head. snd. reduceUntil (const False). foldl shiftReduce ([],[xComb]) $ xs 	where shiftReduce s x = (x:) *** (xComb:) $ reduceUntil (x <) s 		reduce (op:ops,v1:v2:vs) = (ops,App v2 v1:vs) reduce ([],[val]) = ([],[val]) reduceUntil p = until (all p . take 1 . fst) reduce

Runtime system
The runtime system is borrowed from Lazy K (and this could very well be implemented as an additional input language for Lazy K). The list of numbers is parsed into a lambda expression, which is evaluated by a lazy interpreter, with input represented as an infinite list of church-encoded ascii values, and the program treated as an infinte list of output characters.

Implementation
There is a reference implementation in Haskell at http://darcs.olsner.se/1337/ (using darcs get is recommended). This implementation is rather slow, and can in its current incarnation only calculate the first few primes in one second (a long way from the 80 claimed for Lazy K). This is probably caused by program pessimisation in the SKI-to-SK-to-X conversion process - as an example, for the simplest SKI program possible, I, the above skToNum function produces a seven line lambda expression when parsed: I -> SKK -> X(XX)(XX)(XX) -> etc.