Jump to content

Brainfuck Interpreter


torels
 Share

Recommended Posts

Hi There!

I just wrote a brainfuck interpreter 'cause I had nothing to do XD

here's the code

;brainfuck interpreter
Global $input, $Array[1]
$pos = 0
$current=0

$HelloWorld = "++++++++++ [ >+++++++ >++++++++++ >+++ >+ <<<<- ] >++. >+. +++++++. . +++. >++. " & _
"<<+++++++++++++++. >. +++. ------. --------. >+. >."

$CAT=",[.,]"

_Run($HelloWorld)
ConsoleWrite(@CRLF)
_Run($CAT)
ConsoleWrite(@CRLF)

Func _Run($Code)
    For $i = 1 to StringLen($Code)
        $String=StringMid($Code, $i, 1)
        Switch $String
            Case ">"
                $current+=1
                ReDim $Array[Ubound($Array)+1]
            Case "<"
                $current-=1
            Case "+"
                $Array[$current]=$Array[$current]+1
            Case "-"
                $Array[$current]=$Array[$current]-1
            Case "."
                ConsoleWrite(Chr($Array[$current]))
            Case ","
                If $pos = 0 Then
                    $input = InputBox("Char", "Type a String", "", "", -1, 120)
                    ConsoleWrite(@CRLF)
                EndIf
                $pos += 1
                $Char = StringMid($input, $pos, 1)
                $Array[$current]=Asc($Char)
                If $pos = StringLen($input) Then $pos = 0
            Case "["
                $loop = ""
                $ct = $i
                Do
                    $ct += 1
                    $loop &= StringMid($Code, $ct, 1)
                Until StringRight($loop, 1)="]"
                $loop = StringLeft($loop, StringLen($loop) -1)
                While $Array[$current]>1
                    _Run($loop)
                WEnd
            EndSwitch
    Next
EndFunc

For more information on brainfuck go to http://esoteric.voxelperfect.net/wiki/Brainfuck

Some Projects:[list][*]ZIP UDF using no external files[*]iPod Music Transfer [*]iTunes UDF - fully integrate iTunes with au3[*]iTunes info (taskbar player hover)[*]Instant Run - run scripts without saving them before :)[*]Get Tube - YouTube Downloader[*]Lyric Finder 2 - Find Lyrics to any of your song[*]DeskBox - A Desktop Extension Tool[/list]indifference will ruin the world, but in the end... WHO CARES :P---------------http://torels.altervista.org

Link to comment
Share on other sites

Fucking funny but entirely useless.

it is indeed! :mellow:

Some Projects:[list][*]ZIP UDF using no external files[*]iPod Music Transfer [*]iTunes UDF - fully integrate iTunes with au3[*]iTunes info (taskbar player hover)[*]Instant Run - run scripts without saving them before :)[*]Get Tube - YouTube Downloader[*]Lyric Finder 2 - Find Lyrics to any of your song[*]DeskBox - A Desktop Extension Tool[/list]indifference will ruin the world, but in the end... WHO CARES :P---------------http://torels.altervista.org

Link to comment
Share on other sites

  • 1 month later...

I don't want to revive this thread more than a month, but you may have a problem in your interpreter.

Your code for the '[' operator appears to search for the first ']' to match it.

However, be advised that Brainfuck supports bracket nesting:

"[ [ ] ]" where the two bolds match and two nonbolds match

It would seem in this condition your code would assume the following to match:

"[ [ ] ]" (first [ and first ] )

As an example, you may try to execute the following code:

,[.[-],]

This code is perfectly valid and it for our purposes should work like your CAT except it should null the current char (with "[-]") before inputting another. (which wouldn't do much in this case anyway)

However, your code doesn't support nesting like regular BF does and ends up in an infinite do-until loop looking for an ending bracket in the wrong place. See below for what happened:

Here's what your script appears to do with that code:

execute ",[.[-],]"
recursion level 1: 
 - Input char
 - found operator "["
 - loop until "]" is found at the last buffer position
 - {
 -  - read next char to buffer "."
 -  - read next char to buffer "["
 -  - read next char to buffer "-"
 -  - read next char to buffer "]"
 -  - found "]" at the last buffer position, end loop.
 - }
 - Trim off the last char of the buffer (".[-]" -> ".[-")
 - loop while current char is not null:
   {
 -  - execute ".[-"
   }

recursion level 2:
 - output char
 - found operator "["
 - loop until "]" is found at the last buffer position
 - {
 -  - read next char to buffer "-"
 -  - read next char to buffer "" (none)
 -  - read next char to buffer "" (none)
 -  - read next char to buffer "" (none)
 -  - ...
 -  - ... Infinite Do-Until loop looking for ending bracket.
 - }

You can check that this is what is happening by putting a ConsoleWrite into your Do-Until loop.

Ref on brackets:

[ if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command*.

] if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command*.

*[ and ] match as parentheses usually do: each [ matches exactly one ] and vice versa, the [ comes first, and there can be no unmatched [ or ] between the two.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Link to comment
Share on other sites

  • 2 weeks later...

Since I critiqued your interpreter in the previous post, I decided to put my money where my mouth is, so to speak, and try to implement it.

Global $tData=DllStructCreate('BYTE[65536]')
Global $pData=0

$HelloWorld = "++++++++++ [ >+++++++ >++++++++++ >+++ >+ <<<<- ] >++. >+. +++++++. . +++. >++. " & _
"<<+++++++++++++++. >. +++. ------. --------. >+. >."

$Cat = ",[.,]"

$CatWithNesting = ",[.[-],]"

ConsoleWrite('HelloWorld: '&@CRLF)
_Run_handled($HelloWorld)
ConsoleWrite(@CRLF&'Cat: '&@CRLF)
_Run_handled($Cat)
ConsoleWrite(@CRLF&'CatWithNesting: '&@CRLF)
_Run_handled($CatWithNesting)

Func _Run_handled($Code)

    Local $aError[6]=['','Unmatched closing bracket during search','Unmatched opening bracket during search','Unexpected closing bracket','Data pointer passed left boundary','Data pointer passed right boundary']
    Local $sError=''
    Local $i=_Run($Code)
    If @error>=0 And @error<6 Then $sError=$aError[@error]
    If StringLen($sError) Then MsgBox(16,'Brainfuck Interpreter Error','ERROR: '&$sError&'.'&@CRLF&'Ending Instruction Pointer: '&($i-1)&@CRLF&'Current Data Pointer: '&$pData)
EndFunc

Func _Run($Code,$iStart=1,$iEnd=0)
    If $iEnd<1 Then $iEnd=StringLen($Code)
    For $i = $iStart to $iEnd
        Switch StringMid($Code, $i, 1)
            Case ">"
                $pData+=1
                If $pData=65536 Then Return SetError(5,0,$i)
            Case "<"
                $pData-=1
                If $pData<0 Then Return SetError(4,0,$i)
            Case "+"
                DllStructSetData($tData,1,DllStructGetData($tData,1,$pData+1)+1,$pData+1)
            Case "-"
                DllStructSetData($tData,1,DllStructGetData($tData,1,$pData+1)-1,$pData+1)
            Case "."
                ConsoleWrite(Chr(DllStructGetData($tData,1,$pData+1)))
            Case ","
                ;NOTE: Strongly suggest replacing with a console input method
                Local $cIn=StringMid(InputBox('Brainfuck Interpreter','Enter one character'),1,1)
                DllStructSetData($tData,1,Asc($cIn),$pData+1)
            Case "["
                Local $iStartSub=$i
                Local $iEndSub=_MatchBracket($Code,$i,$iEnd)
                If @error<>0 Then Return SetError(@error,0,$iEndSub); Error detected in bracket matching
                While DllStructGetData($tData,1,$pData+1)<>0
                    Local $iRet=_Run($Code,$iStartSub+1,$iEndSub-1)
                    If @error<>0 Then Return SetError(@error,0,$iRet); Error detected in subroutine
                WEnd
                $i=$iEndSub;this will get incremented, so the ] is skipped.
            Case ']'
                ; the code in [ should have skipped past this - so error
                Return SetError(3,0,$i)
        EndSwitch
    Next
    Return 0
EndFunc

Func _MatchBracket($Code,$iStart=1,$iEnd=0); -2=unmatched opening bracket; -1=unmatched closing bracket; 0=no brackets; +i=first bracket balanced at position 'i'
    If $iEnd<1 Then $iEnd=StringLen($Code)
    Local $Open=0
    For $i=$iStart To $iEnd
        Switch StringMid($Code,$i,1)
            Case '['
                $Open+=1
            Case ']'
                $Open-=1
                If $Open=0 Then Return $i
                If $Open<0 Then Return SetError(1,0,$i);shouldn't be possible since _MatchBracket is only called on opening brackets and returns on the final closing bracket.
        EndSwitch
    Next
    If $Open>0 Then Return SetError(2,0,$i)
    Return 0
EndFunc

This interpreter has the following specifications:

  • Bracket nesting ( [[]] )
  • GUI Input for characters like yours (Strongly suggest changing to Console Input)
  • 65536 cells supported (Yours: Unbounded; but I didn't want to use an AutoIt Array and ReDim)
  • Data pointer boundaries: 0-65535
  • Minimum Data Pointer boundary violation behavior: Handled Error (Yours: Unhandled AutoIt error, 0-bounded leftward)
  • Maximum Data Pointer boundary violation behavior: Handled Error (Yours: N/A, Unbounded rightward)
  • Input EOF behavior: cell set to 0 (Yours: same)
  • Cell byte integer overflow behavior: unsigned byte wrap-around (0-255) (Yours: Int64 unwrapped? :blink: )
  • Non-command character behavior: Ignore

Ref on standards:

... as well as an array of at least 30,000 byte cells ...

In the classic distribution, the cells are of 8-bit size (cells are bytes), and this is still the most common size.

The behavior of the , command when an end-of-file condition has been encountered varies. ... There is no real concensus...

When the pointer moves outside the bounds of the array, some implementations will give an error message, some will try to extend the array dynamically, some will not notice and will produce undefined behavior, and a few will move the pointer to the opposite end of the array.

Edit: Shortened the error-message code.

Edit: Matching bracket search shortened during nesting.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...