Execute Brain****/F Sharp

From Rosetta Code
Execute Brain****/F Sharp is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/F Sharp is part of RCBF. You may find other members of RCBF at Category:RCBF.

An implementation of Brainf*** in F#.


<lang fsharp>open System

let RCBF (pgmStr : string) =

   let pgm = Seq.toArray pgmStr                                        // Turn program into an array
   let ptr = ref 0                                                     // Pointer into input
   let ip = ref 0                                                      // Instruction Pointer
   let input = ref (Array.create 100 0)
   let InputNumber() =
       let mutable fValid = false
       let mutable num = 0
       printfn "Enter a valid number"
       fValid <- Int32.TryParse(Console.ReadLine(), &num);
       while not fValid do
           printfn "Invalid input.  Please enter a valid number"
           fValid <- Int32.TryParse(Console.ReadLine(), &num);
       num
   let InputAscii() =
       printfn "Enter an ascii character"
       let chOut = (Console.ReadKey().KeyChar)
       printfn ""
       int chOut
   let AdvanceIp() = ip := !ip + 1                                     // Advance IP
   let RetreatIp() = ip := !ip - 1                                     // Decrement IP
   let SkipBrackets fForward =
       if (!input).[!ptr] <> 0 then                                       // If we have a 0 input
           AdvanceIp()                                                 // Then just advance to next instruction
       else                                                            // otherwise
           let fnMove = if fForward then AdvanceIp else RetreatIp      // get the appropriate function to move forward or backward
           let mutable cBrackets = 1                                   // Count of brackets we've seen
           while cBrackets > 0 do                                      // While we have unmatched brackets
               fnMove()                                                // move to the next character
               if !ip >= 0 && !ip < pgm.Length then                    // and if we're still within range
                   match pgm.[!ip] with                                // look at the character
                   | '[' -> cBrackets <- cBrackets + 1                 // If it's a '[' then count up brackets
                   | ']' -> cBrackets <- cBrackets - 1                 // If it's a ']' then count down brackets
                   | _ -> ignore(0)                                    // Ignore anything else
           AdvanceIp()                                                 // When we're on the matching bracket, skip to the next instruction
   let MovePtr fRight =
       if fRight then
           ptr := !ptr + 1
           if !ptr >= (!input).Length then
               Array.Resize(input, (!input).Length + 20)
       else
           ptr := !ptr - 1
           if !ptr < 0 then
               let newInput = Array.create ((!input).Length + 20) 0
               Array.ConstrainedCopy(!input, 0, newInput, 20, (!input).Length)
               ptr := 19
   let interpretCmd() =
       match pgm.[!ip] with
       | '>' -> MovePtr true; AdvanceIp()
       | '<' -> MovePtr false; AdvanceIp()
       | '+' -> (!input).[!ptr] <- (!input).[!ptr] + 1; AdvanceIp()
       | '-' -> (!input).[!ptr] <- (!input).[!ptr] - 1; AdvanceIp()
       | '.' -> printf "%c" (char (!input).[!ptr]); AdvanceIp()
       | ',' -> (!input).[!ptr] <- InputNumber(); AdvanceIp()
       | '~' -> (!input).[!ptr] <- InputAscii(); AdvanceIp()
       | '[' -> SkipBrackets true
       | ']' -> SkipBrackets false
       | _ -> AdvanceIp()
   while !ip >= 0 && !ip < pgm.Length do
interpretCmd()</lang>

Hello world in RCBF (stolen from the Wiki site):

<lang fsharp>let pgmHelloWorld = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."

let tape = Array.create 5 0

Rcbf pgmHelloWorld tape</lang>