Brainfunct

Brainfunct is a functional esoteric programming language based on brainfuck, created by User:Koen in 2012 when he observed a lack of functional languages among the plethora of Brainfuck derivatives. A program in brainfunct consists in a succession of declaration of functions. Functions have no name but have a number, corresponding to the order in which they are declared. Functions operates on a tape similar to brainfuck's. The commands are:
Command	Description
> 	Move the pointer to the right
< 	Move the pointer to the left
+ 	Increment the memory cell under the pointer
- 	Decrement the memory cell under the pointer
. 	Output the character signified by the cell at the pointer
, 	Input a character and store it in the cell at the pointer
@ 	Call the function signified by the cell under the pointer
==Function declaration==
There are two versions of Brainfunct. The only difference is the syntax for function declaration.
===Brainfunct-slash===
In brainfunct-slash, functions are simply separated by the symbol /. The first function is number 1. The last function is the main function; it cannot be called by other functions, but it is called when the execution starts.
===Brainfunct-nested===
The great addition of brainfunct-nested is the use of parenthesizing instead of the simple /. This allows for nested functions. Nested functions cannot be called from out of the function where they are declared. The number of a function is the smallest number available within their scope, starting with less deep functions. All commands not included in a function are part of the main function. The following is an example of how functions are numbered in this version:
 (1) (2) (((7)6)3) (4) (((8)6)(7)5) main
==Sample programs==
===Truth-machine===
 ////////////////////////////////////////////////.@/,.@
In this program the first 48 functions are no-ops, and the 49th (49 being the ASCII code for '1') is an infinite loop of printing character '1'.
===Cat program===
 >,.<@/+@
Doesn't handle end of file. The implementation below doesn't either, though.
==Syntactic sugar==
To avoid "flooding" a program with the symbol /, the body of a function may be preceded by the function number. The function number must be written in octal; using this notation, the truth-machine above would become:
 61.@/,.@
==Implementations==
===Ocaml===
Note: This interpreter supports brainfunct-slash only.
let tape_size = 100;; (* ideally the tape would be unbounded *)
let n_functions = 260;; (* ideally the number of functions would be unbounded *)
let tape = Array.make tape_size 0;;
let ptr = ref 0;;
let f = Array.make n_functions "";;
let make_functions s =
 let i = ref 0 and j = ref 1 and l = String.length s in
 for k = 0 to (l - 1) do
 if s.[k] = '/' then
 begin
 f.(!j) <- String.sub s !i (k - !i);
 i := k+1; incr j
 end
 done;
 f.(0) <- String.sub s !i (l - !i);;
exception Unknown_command of char;;
let rec mtch c =
 match c with
 | '>' -> incr ptr
 | '<' -> decr ptr
 | '+' -> tape.(!ptr) <- succ tape.(!ptr)
 | '-' -> tape.(!ptr) <- pred tape.(!ptr)
 | '.' -> print_char (char_of_int tape.(!ptr)); flush(stdout)
 | ',' -> tape.(!ptr) <- (try int_of_char (input_char stdin) with | End_of_file -> -1)
 | '@' -> interpret tape.(!ptr) false
 | x -> raise (Unknown_command x)
and interpret fn first_time =
 if (fn > 0 || first_time) then
 let l = String.length f.(fn) - 2
 in
 for k = 0 to l do
 mtch f.(fn).[k] done;
 mtch f.(fn).[l + 1];;
make_functions Sys.argv.(1);;
interpret 0 true;;
===Haskell===
Supports both slashes and parentheses, including in weird nested combinations, essentially desugaring the former to the latter. Does not support the function number syntactic sugar.
import Control.Monad.State (StateT, evalStateT, gets, liftIO, modify)
import Data.Functor ((<$>), (<$))
import System.Environment (getArgs)
import System.IO (hFlush, hIsEOF, hPutStr, stderr, stdin, stdout)
import Text.Parsec (Parsec, between, char, choice, eof, many, parse, sepBy1, spaces, (<|>))
data Tape = Tape { left, right :: [Int] }
data CmdOrFun = Cmd (FunList -> BF) | Fun (FunList -> BF)
type BF = StateT Tape IO ()
type FunList = [BF]
op :: Char -> Parsec [Char] () ()
op c = char c >> spaces
cmdOrSubfun :: Parsec [Char] () CmdOrFun
cmdOrSubfun =
 Fun <$> between (op '(') (op ')') function <|>
 Cmd (\funList -> findFun funList =<< getCurrent) <$ op '@' <|>
 Cmd . const <$> choice [
 modify (\(Tape ls (cur:rs)) -> Tape (cur:ls) rs) <$ op '>',
 modify (\(Tape (l:ls) rs) -> Tape ls (l:rs)) <$ op '<',
 modify (\(Tape ls (cur:rs)) -> Tape ls (cur+1:rs)) <$ op '+',
 modify (\(Tape ls (cur:rs)) -> Tape ls (cur-1:rs)) <$ op '-',
 (getCurrent >>= \c -> liftIO $ putChar (toEnum c) >> hFlush stdout) <$ op '.',
 (do c <- liftIO $ do
 e <- hIsEOF stdin
 if e then return (-1) else fromEnum <$> getChar
 modify (\(Tape ls (_:rs)) -> Tape ls (c:rs))) <$ op ',' ]
 where
 getCurrent = gets (head . right)
 findFun fs n
 | n > 0, f:_ <- drop (n-1) fs = f
 | otherwise = return ()
function :: Parsec [Char] () (FunList -> BF)
function = makeFunction . unslash <$> sepBy1 (many cmdOrSubfun) (op '/')
 where
 unslash blocks = map (Fun . makeFunction) (init blocks) ++ last blocks
 makeFunction cfs funList = sequence_ [cmd funList' | Cmd cmd <- cfs]
 where
 funList' = funList ++ [fun funList' | Fun fun <- cfs]
runBF :: String -> String -> IO ()
runBF sourceName s = case parse (between spaces eof function) sourceName s of
 Left err -> hPutStr stderr $ "Parse error: " ++ show err
 Right f -> evalStateT (f []) $ Tape (repeat 0) (repeat 0)
main = runBF "command line" . unwords =<< getArgs
==Computational Class==
:Note: The Computational Class of this language hasn't been proven yet, so please take the following information with a grain of salt.
The computational class of the two versions of brainfunct are currently unknown. However the conjectured computational classes are that brainfunct-slashes is Turing Incomplete, while brainfunct-nested is Turing Complete.
==See also==
* pbrain, another brainfuck derivative based on the same idea
* BFI, also a functional brainfuck derivative, which uses an extra "routine pointer" for function calls
* brainFn, a functional brainfuck derivative inspired by Brainfunct that implements labels and function concatenation.
Category:Languages
Category:Brainfuck derivatives
Category:Functional paradigm
Category:Unknown computational class
Category:Cell-based
Category:Low-level
Category:Implemented
Category:2012