├── 99bottles.b ├── README.md ├── bench.b ├── bottles.b ├── example1.py ├── example2.py ├── example3.py ├── example4.py ├── example5.py ├── hanoi.b ├── mandel.b └── tutorial.rst /99bottles.b: -------------------------------------------------------------------------------- 1 | # 99 bottles of beer in Brainf*ck 2 | # Copyright (C) 2008 Raphael Bois 3 | # 1671 brainf*ck instructions. 4 | # Published under GPL v2 5 | 6 | Initialization 7 | ++ Counter for loop (a) 8 | >+ unused 9 | >++ Counter for loop (b) 10 | > Flag for 'no more' 11 | >+ Flag for not 'no more' 12 | >>> (5) to (7) : temporary values 13 | ++++++++++[->+>+>++++++++++<<<]>>> 10 10 100 in (8) (9) (10) 14 | >++++++++++ 10 in (11) 15 | [- 16 | >+++++ 50 in (12) 17 | >++++++++++ 100 in (13) 18 | >+++++++++++ 110 in (14) 19 | >++++++++ 80 in (15) 20 | >++++++++ 80 in (16) 21 | >+++ 30 in (17) 22 | >++++ 40 in (18) 23 | >+ 10 in (19) 24 | <<<<<<<<] 25 | + 26 | >-- + 48 '0' plus 1 in (12) 27 | >++ + 102 'f' plus 1 in (13) 28 | >+++++ + 115 's' plus 1 in (14) 29 | >-- + 78 'N' plus 1 in (15) 30 | >++++ + 84 'T' plus 1 in (16) 31 | >++ + 32 ' ' plus 1 in (17) 32 | >++++ + 44 comma plus 1 in (18) 33 | > + 10 LF plus 1 in (19) 34 | 35 | stuff for writing parts of the song 36 | >+ select stuff 37 | >+ select stuff 38 | >+ write song part 3 39 | >++ write song part 1 40 | >+ write song part 2 41 | >+ Flag for 'end of song' 42 | >++ Flag for not 'end of song' 43 | 44 | All bytes are at val plus 1 45 | Go back to (7) with final initialization step (remove 1 to all bytes) 46 | [-<] 47 | 48 | <<<<<<< at (0) 49 | [ loop (a) 50 | - 51 | 52 | >> at (2) 53 | [ loop (b) 54 | 55 | >>>>>>>> at (10) 56 | [ start loop 57 | 58 | <<<<<<< at (3) 59 | [->[-] 60 | print '(N|n)o more' 61 | >>>>>>>>>>>. '(N|n)' 62 | <----. 'o' 63 | >>>. ' ' 64 | <<<--. 'm' 65 | ++. 'o' 66 | +++.+ 'r' 67 | <-.+ 'e' 68 | <<+<<<<<<<< 69 | ]+> at (4) 70 | [-<[-]>>>>> at (9) 71 | prints number (using (9) and (10)) 72 | [>>>+<<<<+<+<+>>>-]<<<[->>>+<<<]> at (6) 73 | [>>>>>>+<<<<<<-]>>>>>[[-]>.<]<<<<[>>>>>-<<<<<-]>> at (9) 74 | [<<+<+<+>>>>-]<<<<[->>>>+<<<<]> at (6) 75 | [>>>>>>+<<<<<<-]>>>>>>.<<<<<[>>>>>-<<<<<-] at (7) 76 | 77 | memorize in (11) if (10) not 1 78 | >>>[-<<<+<+>>>>]<<<<[->>>>+<<<<]>-[[-]>>>>+<<<<]<<< at (4) 79 | ]+ 80 | 81 | >>>>>>>> at (12) 82 | print ' bottle(s) of beer' 83 | >>>>>. ' ' 84 | <<<<----. 'b' 85 | >----. 'o' 86 | +++++..- 'tt' 87 | <++++++++++. 'l' 88 | -------. 'e' 89 | <<[[-]>>>.<<<]>> 's' if (11)==1 ie if (10)!=1 90 | >>>>. ' ' 91 | <<<----. 'o' 92 | <+. 'f' 93 | >>>>. ' ' 94 | <<<<----. 'b' 95 | +++..+ 'ee' 96 | >+++.+ 'r' 97 | 98 | [>] at (20) 99 | 100 | +>+>[->+<<-<- 101 | print ' on the wall' DOT LF LF 102 | <<<. ' ' 103 | <<<----. 'o' 104 | -. 'n' 105 | >>>. ' ' 106 | <<<++++++. 't' 107 | <++. 'h' 108 | ---. 'e' 109 | >>>>. ' ' 110 | <<<+++. 'w' 111 | <----. 'a' 112 | +++++++++++.. 'll' 113 | ------>---- reset to 'f' and 's' 114 | >---------- ---------- ---------- -- sets (15) to 'N' 115 | 116 | >>>++.-- DOT 117 | >.. LF LF 118 | >>>] at (22) 119 | 120 | >>>[->[-]<<<<<<<[<]<[-]>>[>]>>>>>]+ if end of song reset bottles counter 121 | >[-<[-] at (25) 122 | <<<< at (21) 123 | [->>[->+<<<<- 124 | print ' on the wall' COMMA ' ' 125 | <<<. ' ' 126 | <<<----. 'o' 127 | -. 'n' 128 | >>>. ' ' 129 | <<<++++++. 't' 130 | <++. 'h' 131 | ---. 'e' 132 | >>>>. ' ' 133 | <<<+++. 'w' 134 | <----. 'a' 135 | +++++++++++.. 'll' 136 | 137 | ------>---- reset (13) and (14) to 'f' and 's' 138 | >++++++++++ ++++++++++ ++++++++++ ++ sets (15) to 'n' 139 | 140 | >>>. comma 141 | <. ' ' 142 | >>>>>>]<<]< at (20) 143 | 144 | [->>>>[-<<+< at (21) 145 | <<<++.-- DOT 146 | >. LF 147 | 148 | [<]<<<<<<<< at (3) 149 | [->[-]<]+> at (4) 150 | [-<[-]> 151 | >>>>>>>>>>>>. 'T' 152 | <<<-----. 'a' 153 | ++++++++++. 'k' 154 | ------. 'e' 155 | >>>>. ' ' 156 | <<<----. 'o' 157 | -. 'n' 158 | <. 'e' 159 | >>>>. ' ' 160 | <<<<-. 'd' 161 | >+. 'o' 162 | ++++++++. 'w' 163 | ---------. 'n' 164 | >>>. ' ' 165 | <<<<---. 'a' 166 | >. 'n' 167 | <+++. 'd' 168 | >>>>. ' ' 169 | <<<++. 'p' 170 | <---. 'a' 171 | >+++.. 'ss' 172 | >>>. ' ' 173 | <<<<++++++++. 'i' 174 | >+. 't' 175 | >>>. ' ' 176 | <<<<--------. 'a' 177 | >--. 'r' 178 | ---. 'o' 179 | ++++++. 'u' 180 | -------. 'n' 181 | <+++. 'd' 182 | ++>+++++ reset (13) and (14) to 'f' and 's' 183 | >>>>. comma 184 | <. ' ' 185 | 186 | [<]<<<<<<< at (4) 187 | ]+ 188 | 189 | >>>>>> at (10) 190 | decrements values 191 | -<<<+>>[<<[-]<+<+>>>>-]<<<<[>-<[-]]>[->>>+<<<]>[->->+++++++++<<]>>> at (10) 192 | 193 | >>[>]>>>>] at (24) 194 | <<<<] at (20) 195 | 196 | >>>>>>]+ at (26) 197 | 198 | <<<<<<<[<]< at (10) 199 | ] 200 | +<+ 201 | <<<<<<+< at (2) 202 | - 203 | ] 204 | 205 | print 'Go to the store and buy some more' comma ' ' 206 | 207 | >>>>>>>>>>[>]>>>>> at (25) 208 | [->[-]<]+> at (26) 209 | [-<[-] 210 | <<<<<<<<< at (16) 211 | -------------. 'G' 212 | <<----. 'o' 213 | >>>. ' ' 214 | <<<+++++. 't' 215 | -----. 'o' 216 | >>>. ' ' 217 | <<<+++++. 't' 218 | <++. 'h' 219 | ---. 'e' 220 | >>>>. ' ' 221 | <<<-. 's' 222 | +. 't' 223 | -----. 'o' 224 | +++. 'r' 225 | <. 'e' 226 | >>>>. ' ' 227 | <<<<----. 'a' 228 | >----. 'n' 229 | <+++. 'd' 230 | >>>>. ' ' 231 | <<<<--. 'b' 232 | >+++++++. 'u' 233 | ++++. 'y' 234 | >>>. ' ' 235 | <<<------. 's' 236 | ----. 'o' 237 | --. 'm' 238 | <+++. 'e' 239 | >>>>. ' ' 240 | <<<. 'm' 241 | ++. 'o' 242 | +++.+ 'r' 243 | <.+ 'e' 244 | >>>>>. coma 245 | <. ' ' 246 | >>>>>>>>> 247 | ]+ 248 | 249 | Initialize last loop to print final '99 bottles of beer on the wall' DOT 250 | <[-]+<[-]<[-]<[-]+<<< at (19) 251 | [<]<[-]<[-]<[-]<[-] at (7) 252 | ++++++++++[->+>+>++++++++++<<<]>->->- 253 | <<<<<<[-]+<[-]<+<< at (0) 254 | ] 255 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PyPy로 인터프리터 작성하기 2 | ========================== 3 | 이 글은 Andrew Brown 에 의해 작성되었으며, 4 | pypy-dev 메일링 리스트에 있는 개발자들의 도움을 받았습니다. 5 | 6 | 이 튜토리얼의 원본과 주변 파일들은 7 | https://bitbucket.org/brownan/pypy-tutorial/ 에서 구할 수 있습니다. 8 | 9 | 제가 처음 PyPy 프로젝트를 알게 되었을 때는 이게 대체 무엇인지 깨닫는 데 시간이 10 | 꽤 걸렸습니다. 저와 같은 사람들을 위해 설명하자면 PyPy는 다음의 두 부분으로 11 | 요약할 수 있습니다: 12 | 13 | * 인터프리터 구현을 위한 도구의 집합 14 | * 그것을 사용하여 만들어진 파이썬 구현체 15 | 16 | 두 번째 부분은 아마 대부분의 사람들이 생각하는 PyPy일 것입니다. 17 | 하지만 이 튜토리얼에서는 그 파이썬 인터프리터에 대해서는 다루지 *않습니다*. 18 | 이 튜토리얼은 자신의 언어를 위한 인터프리터를 직접 구현하는 법에 대한 19 | 내용입니다. 20 | 21 | 이는 저 스스로 PyPy가 정확히 무엇인지, 어떻게 동작하는지를 이해하기 위해 진행한 22 | 프로젝트이기도 합니다. 23 | 24 | 이 튜토리얼은 독자가 PyPy를, 그것이 어떻게 돌아가는지를, 심지어 그게 무엇인지를 25 | 잘 모를 수 있을 것이라 가정합니다. 저는 처음부터 차근차근 설명할 요량입니다. 26 | 27 | PyPy는 무엇을 하는가 28 | -------------------- 29 | PyPy가 무엇을 할 수 있는지 대략적인 개요를 설명하겠습니다. 30 | 일단 여러분이 인터프리터를 하나 만들고 싶다고 칩시다. 31 | 그 인터프리터는 소스코드 파서와, 바이트코드 해석 루프, 32 | 그 외에 잡다한 표준 라이브러리 코드를 포함하는 거구요. 33 | 34 | 적당히 복잡한 언어라면 작업량이 꽤나 되겠죠. 그리고 상당한 로우레벨 작업이 35 | 수반됩니다. 파서와 컴파일러 코드를 작업하는 건 대체로 재미가 없는 작업이라, 36 | 세상에는 파서와 컴파일러를 자동으로 생성해주는 도구가 존재합니다. 37 | 38 | 그럼에도 인터프리터를 구현하려면 메모리 관리를 고려해야 하고, 임의의 정밀도를 39 | 가진 정수나 멋지게 일반화된 해시테이블 등을 원한다면 바퀴를 다시 만드는 노력이 40 | 필요합니다. 41 | 이는 누군가 언어를 하나 만들고 싶다는 생각을 무르게 만드는 데 충분한 요소입니다. 42 | 43 | 파이썬같이, 이미 존재하는 고수준 언어 위에서 자신의 언어를 작성할 수 있다면 44 | 멋지겠죠? 자동화된 메모리 관리나 풍부한 자료구조 등 고수준 언어에 구현된 기능을 45 | 그대로 가져다 사용할 수 있을 겁니다. 46 | 47 | 엇, 근데 인터프리터 위에서 돌아가는 인터프리터라면 많이 느리지 않을까요? 48 | 그렇게 만들어버린다면 인터프리팅이 두 번에 걸쳐서 일어날 텐데요. 49 | 50 | 눈치 채셨겠지만 PyPy는 이 문제를 해결합니다. PyPy는 여러분의 인터프리터 코드를 51 | 분석 및 C 코드(또는 JVM이나 CLI)로 변환하기 위한 정교한 툴체인입니다. 52 | 이 툴체인은 "변환(translation)"을 수행하기 위해, 어떻게 많은 파이썬 문법과 53 | 표준 라이브러리들을 옮겨내야 하는지를 알고 있습니다. 여러분이 작업해야할 것은 54 | 여러분의 인터프리터를 파이썬의 서브셋인 **RPython**으로 작성하는 것뿐입니다. 55 | RPython은 분석과 변환 작업 및 매우 효율적인 인터프리터를 생성할 수 있도록 56 | 매우 조심스럽게 정의된 언어입니다. 57 | 58 | 효율적인 인터프리터는 작성하기 쉬워야 하니까요. 59 | 60 | 언어 61 | ---- 62 | 구현하기에 굉장히 쉬운 언어를 하나 골랐습니다. 런타임은 모두 `0`으로 초기화된 63 | 정수 테이프와, 테이프 중 한 칸을 가리키는 포인터 하나로 구성되어 있는 언어인데, 64 | 이 언어는 8가지 명령어로 구성되어 있습니다: 65 | 66 | ### > 67 | 테이프 포인터를 오른쪽으로 한 칸 이동시킵니다. 68 | 69 | ### < 70 | 테이프 포인터를 왼쪽으로 한 칸 이동시킵니다. 71 | 72 | ### + 73 | 포인터가 가리키는 칸의 값을 증가시킵니다. 74 | 75 | ### - 76 | 포인터가 가리키는 칸의 값을 감소시킵니다. 77 | 78 | ### [ 79 | 만약 포인터가 가리키는 칸의 값이 `0`이라면 상응하는 괄호짝 `]` 뒤로 건너뜁니다. 80 | 81 | ### ] 82 | 상응하는 괄호짝 `[`로 돌아갑니다 (반복 조건도 평가합니다). 83 | 84 | ### . 85 | 포인터가 가리키는 칸의 값을 `stdout`으로 한 바이트 출력합니다. 86 | 87 | ### , 88 | `stdin`에서 한 바이트 읽어와 포인터가 가리키는 칸에 대입합니다. 89 | 90 | 인식되지 않는 바이트들은 무시합니다. 91 | 92 | 이게 무엇인지 아는 분들이 있으시겠죠. 전 앞으로 이것을 BF라고 부르겠습니다. 93 | 94 | 한 가지 주목할 점은 이 언어는 바이트코드가 바로 언어 자신이라는 점입니다; 95 | 달리 소스코드를 바이트코드로 변환할 필요가 없습니다. 96 | 따라서 이 언어는 읽는 즉시 해석할 수 있습니다: 97 | 우리 인터프리터의 메인 평가 루프는 소스코드에 작성된 그대로 돌아갈 겁니다. 98 | 이런 건 구현이 매우 단순하게 됩니다. 99 | 100 | 첫 걸음 101 | ------- 102 | 일반적인 파이썬 문법으로 BF 인터프리터를 작성하는 것부터 시작해봅시다. 103 | 가장 먼저, 평가 루프를 작성합니다: 104 | 105 | ```python 106 | def mainloop(program): 107 | tape = Tape() 108 | pc = 0 109 | while pc < len(program): 110 | code = program[pc] 111 | 112 | if code == ">": 113 | tape.advance() 114 | elif code == "<": 115 | tape.devance() 116 | elif code == "+": 117 | tape.inc() 118 | elif code == "-": 119 | tape.dec() 120 | elif code == ".": 121 | sys.stdout.write(chr(tape.get())) 122 | elif code == ",": 123 | tape.set(ord(sys.stdin.read(1))) 124 | elif code == "[" and value() == 0: 125 | # Skip forward to the matching ] 126 | elif code == "]" and value() != 0: 127 | # Skip back to the matching [ 128 | 129 | pc += 1 130 | ``` 131 | 132 | 프로그램 카운터(pc)는 현재 명령어의 인덱스를 잡고 있습니다. 133 | 반복문 안쪽의 첫번째 문장에서는 pc가 가리키는 위치에서 명령을 읽어오고, 134 | 그 다음 복합 if 문에선 읽어온 명령을 어떻게 처리할지를 결정합니다. 135 | 136 | 여기에서는 `[`와 `]`의 구현이 빠져있는데, 그 두 개의 명령어는 프로그램 카운터의 137 | 값을 일치하는 짝의 위치로 변경시킬 수 있습니다. (그 후에 `pc`값은 증가하게 되며, 138 | 따라서 반복 조건은 루프의 진입시에 한 번 평가되고, 그 뒤로는 매 주기의 끝마다 139 | 평가됩니다) 140 | 141 | 다음은 테이프 자신의 내용과 그것을 가리키는 포인터를 들고 있는 142 | `Tape` 클래스의 구현입니다: 143 | 144 | ```python 145 | class Tape(object): 146 | def __init__(self): 147 | self.thetape = [0] 148 | self.position = 0 149 | 150 | def get(self): 151 | return self.thetape[self.position] 152 | def set(self, val): 153 | self.thetape[self.position] = val 154 | def inc(self): 155 | self.thetape[self.position] += 1 156 | def dec(self): 157 | self.thetape[self.position] -= 1 158 | def advance(self): 159 | self.position += 1 160 | if len(self.thetape) <= self.position: 161 | self.thetape.append(0) 162 | def devance(self): 163 | self.position -= 1 164 | ``` 165 | 166 | 테이프는 오른쪽으로 필요한 만큼 무한정 확장됩니다. 167 | 포인터가 음수가 되지 않도록 에러 체크를 해줘야 하겠지만 168 | 저는 일단 그 부분은 걱정하지 않도록 하겠습니다. 169 | 170 | 생략한 `[`와 `]` 구현을 제외하면 이 코드는 제대로 돌아갈 것입니다. 171 | 하지만 프로그램이 주석을 많이 갖고 있다면, 172 | 쓸데없이 런타임에 그것들을 뛰어넘는 처리가 일어날 테지요. 173 | 그러니 처음에 한 번 파싱해서 걸러내어 버리도록 합시다. 174 | 175 | 하는 김에 괄호 간에 딕셔너리 매핑을 만들어서, 다음과 같이 짝이 맞는 괄호를 176 | 한 번의 딕셔너리 룩업으로 찾을 수 있게 합시다: 177 | 178 | ```python 179 | def parse(program): 180 | parsed = [] 181 | bracket_map = {} 182 | leftstack = [] 183 | 184 | pc = 0 185 | for char in program: 186 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 187 | parsed.append(char) 188 | 189 | if char == '[': 190 | leftstack.append(pc) 191 | elif char == ']': 192 | left = leftstack.pop() 193 | right = pc 194 | bracket_map[left] = right 195 | bracket_map[right] = left 196 | pc += 1 197 | 198 | return "".join(parsed), bracket_map 199 | ``` 200 | 201 | 이 함수는 모든 불필요한 명령어를 제거한 문자열과, 괄호 인덱스가 짝이 맞는 괄호의 202 | 인덱스로 매핑되는 딕셔너리를 반환합니다. 203 | 204 | 이제 남은 코드들을 이어붙이면 제대로 작동하는 BF 인터프리터가 됩니다: 205 | 206 | ```python 207 | def run(input): 208 | program, map = parse(input.read()) 209 | mainloop(program, map) 210 | 211 | if __name__ == "__main__": 212 | import sys 213 | run(open(sys.argv[1], 'r')) 214 | ``` 215 | 216 | 처음부터 따라오셨다면 `mainloop()`에서 인자를 하나 더 받고 if 문에서 괄호를 217 | 처리하는 부분을 구현하시면 됩니다. 완전한 예제는 다음 파일을 참고하면 됩니다: 218 | [example1.py](./example1.py) 219 | 220 | 지금 바로 인터프리터가 제대로 작동하는지 보기 위해 파이썬으로 돌려볼 수는 221 | 있습니다만, 좀 더 복잡한 예제파일을 돌리기에는 *매우* 느리게 작동할 것입니다: 222 | 223 | ```sh 224 | $ python example1.py 99bottles.b 225 | ``` 226 | 227 | 이 튜토리얼의 저장소에서 `mandel.b`나 다른 예제 프로그램들(제가 작성한 것은 228 | 아닙니다)을 찾아서 돌려보세요. 229 | 230 | PyPy 변환 231 | --------- 232 | 근데 원래 목적은 PyPy를 설명하기 위함이지 BF 인터프리터 튜토리얼이 아니죠. 233 | 여기에 PyPy를 끼얹어서 짱짱-빠른 실행파일로 만들려면 이제 뭘 해야 할까요? 234 | 235 | 잠깐 다른 이야기를 하자면 PyPy 소스 트리에서 pypy/translator/goal 디렉토리에 236 | 들어있는 예제들이 도움이 많이 됩니다. 저는 PyPy의 헬로월드 격인 237 | "targetnopstandalone.py" 예제를 보는 것으로 시작했답니다. 238 | 239 | 다시 예제로 돌아와서, 모듈은 프로그램의 진입 지점을 반환하는 "target"을 정의해야 240 | 합니다. 변환 프로세스는 모듈을 불러와서 "target" 함수를 실행하여 변환을 시작할 241 | 함수 객체를 얻어냅니다: 242 | 243 | ```python 244 | def run(fp): 245 | program_contents = "" 246 | while True: 247 | read = os.read(fp, 4096) 248 | if len(read) == 0: 249 | break 250 | program_contents += read 251 | os.close(fp) 252 | program, bm = parse(program_contents) 253 | mainloop(program, bm) 254 | 255 | def entry_point(argv): 256 | try: 257 | filename = argv[1] 258 | except IndexError: 259 | print "You must supply a filename" 260 | return 1 261 | 262 | run(os.open(filename, os.O_RDONLY, 0777)) 263 | return 0 264 | 265 | def target(*args): 266 | return entry_point, None 267 | 268 | if __name__ == "__main__": 269 | entry_point(sys.argv) 270 | ``` 271 | 272 | 변환 후에 만들어진 실행파일을 돌리면 `entry_point` 함수로 명령행 인자들이 273 | 전달됩니다. 274 | 바뀐 사항들이 몇 가지 더 있는데요, 다음 섹션을 봅시다... 275 | 276 | RPython에 대해서 277 | ---------------- 278 | 지금은 잠깐 RPython을 짚고 넘어가겠습니다. PyPy는 아무 파이썬 코드나 다 279 | 번역할 수 있는 도구가 아닌데, 왜냐하면 파이썬이 너무 동적이기 때문입니다. 280 | 그래서 사용할 수 있는 표준 라이브러리 함수나 문법 구조 등에 몇 가지 제약사항이 281 | 있습니다. 제가 그 제약사항을 일일이 짚고 넘어가진 않을 거고요, 자세한 내용은 282 | [이 문서](https://pypy.readthedocs.org/en/latest/coding-guide.html#id1)를 283 | 보시면 됩니다. 284 | 285 | 위의 예제에서 아마 몇 가지 바뀐 사항들을 확인할 수 있을 겁니다. 전 이제 286 | 파일 객체를 사용하는 대신 저수준의 `os.open`과 `os.read`로 file descriptor를 287 | 사용하고 있습니다. 288 | 위에 써놓진 않았지만 `.`과 `,`의 구현도 비슷하게 변형되어 있습니다. 289 | 이 정도만 맞춰두면 PyPy를 소화해내기 위한 나머지 작업은 단순한 편입니다. 290 | 291 | 그렇게 어렵진 않았죠? 전 아직도 딕셔너리를 사용하고 있고, 길이가 가변적인 292 | 리스트를 사용하는 데다 클래스랑 객체도 활용하고 있답니다! 그리고 지금 사용하는 293 | file descriptor마저 너무 저수준이라 문제라면, PyPy의 "Rpython 표준 라이브러리"에 294 | 포함되어있는 `rlib.streamio`라는 대안도 있습니다. 295 | 296 | 지금까지 다룬 내용이 적용된 예제파일은 여기 있습니다: 297 | [example2.py](./example2.py) 298 | 299 | 변환 300 | ---- 301 | bitbucket.org 저장소에 있는 PyPy 최신 버전을 준비합니다: 302 | 303 | ```sh 304 | $ hg clone https://bitbucket.org/pypy/pypy 305 | ``` 306 | 307 | (제 예제가 돌아가려면 최신 버전에 있는 버그 수정이 반영되어야 해서 그렇습니다.) 308 | 309 | 우리가 돌릴 스크립트는 `pypy/translator/goal/translate.py` 경로에 있습니다. 310 | 이 스크립트에 예제 모듈을 인자로 넣고 돌려봅시다: 311 | 312 | ```sh 313 | $ python ./pypy/rpython/bin/rpython example2.py 314 | ``` 315 | 316 | (속도를 더 내려면 PyPy의 파이썬 인터프리터를 사용해도 되는데, 317 | 꼭 필요한 건 아닙니다.) 318 | 319 | PyPy가 바쁘게 돌아가는 동안 심심하지 않게 콘솔에 예쁜 프랙탈이 그려집니다. 320 | 제 머신에선 20초 정도 걸리네요. 321 | 322 | 다 끝나면 BF 프로그램을 돌릴 수 있는 바이너리가 나옵니다. 323 | 이 튜토리얼 저장소엔 제 컴퓨터에서 45초 정도 걸리는 만델브로트 프랙탈 생성기 등 324 | 몇 가지 BF 프로그램들이 들어있는데, 그 인터프리터로 한 번 돌려보세요: 325 | 326 | ```sh 327 | $ ./example2-c mandel.b 328 | ``` 329 | 330 | 변환을 안 거치고 그대로 파이썬에서 돌릴 경우랑 비교해봅시다: 331 | 332 | ```sh 333 | $ python example2.py mandel.b 334 | ``` 335 | 336 | 안 끝나죠, 그죠? 337 | 338 | 다 했어요. RPython으로 작성한 인터프리터를 339 | PyPy 툴체인으로 별 탈 없이 번역하는데 성공했습니다. 340 | 341 | JIT 끼얹기 342 | ---------- 343 | RPython을 C로 변환한 것까지는 좋은데 PyPy를 사용하면서 344 | *just-in-time 컴파일러를 날로 먹는 기능*을 안 쓰고 넘어가긴 아깝죠. 345 | 네, 인터프리터를 어떻게 구성했는지에 대해서 몇 가지 힌트만 던져주면 346 | PyPy가 알아서 런타임에, 해석된 BF 언어를 기계어로 바꿔주는 347 | JIT 컴파일러를 만들어서, 여러분의 인터프리터에 끼워줍니다! 348 | 349 | 그래서 PyPy한테 그 일을 부탁하려면 뭘 알려줘야 할까요? 350 | 일단 PyPy는 타겟 언어에서(BF) 명령어를 실행한 과정을 쟁여놓고 분석하기 때문에 351 | 여러분의 바이트코드 평가 루프가 어디서 시작하는지를 알아야 합니다. 352 | 353 | 그리고 또 알려줘야 하는 게 특정 실행 프레임을 정의하는 것이 무엇인지인데, 354 | BF는 딱히 스택 프레임을 갖지 않아서, 특정 명령어를 실행하기 위한 상수가 355 | 무엇인지, 그리고 그게 아닌 상수는 무엇인지 정도로 졸아듭니다. 356 | 이것들을 각각 "초록"과 "빨강" 변수라고 부릅니다. 357 | 358 | 잠깐 [example2.py](./example2.py)를 다시 보고 넘어갑시다. 359 | 360 | `mainloop`를 보면 `pc`, `program`, `bracket_map`, `tape` 361 | 이렇게 네 가지 변수가 사용되고 있습니다. 362 | 여기서 `pc`, `program`, `bracket_map`은 초록 변수들입니다. 363 | 그것들은 특정 명령어의 실행을 *정의*하고 있죠. 364 | 만약 JIT 루틴이 같은 조합의 초록 변수들을 먼저 발견한다면 그냥 무시하고 건너뛸지 365 | 반복 구문을 실행해야 할지를 알 수 있게 됩니다. 366 | `tape` 변수는 코드 실행에 의해 조작되는 빨강 변수입니다. 367 | 368 | 이걸 PyPy한테 알려줍시다. 369 | `JitDriver` 클래스를 불러오고 인스턴스를 만드는 것부터 시작합니다: 370 | 371 | ```python 372 | from rpython.rlib.jit import JitDriver 373 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], 374 | reds=['tape']) 375 | ``` 376 | 377 | 그리고 `mainloop` 함수에서 반복문의 제일 상단에 이 코드를 추가합니다: 378 | 379 | ```python 380 | jitdriver.jit_merge_point(pc=pc, tape=tape, program=program, 381 | bracket_map=bracket_map) 382 | ``` 383 | 384 | 그리고 `JitPolicy`도 정의해줘야 합니다. 딱히 대단한 걸 하려는 게 아니므로 385 | 그냥 파일의 아무 곳에 다음과 같이 써주기만 하면 됩니다: 386 | 387 | ```python 388 | def jitpolicy(driver): 389 | from rpython.jit.codewriter.policy import JitPolicy 390 | return JitPolicy() 391 | ``` 392 | 393 | 예제 링크입니다: [example3.py](./example3.py) 394 | 395 | 이제 `--opt=jit` 플래그를 붙여서 다시 번역시켜봅시다: 396 | 397 | ```sh 398 | $ python ./pypy/rpython/bin/rpython --opt=jit example3.py 399 | ``` 400 | 401 | JIT을 활성화시키면 변환이 엄청 오래 걸리고 결과로 뽑히는 바이너리도 훨씬 큽니다. 402 | 제 머신에선 다 번역되는데 거의 8분이 걸렸네요. 403 | 다 끝나면 예의 만델브로트 프로그램을 다시 돌려봅시다. 404 | 번역이 엄청 오래 걸린 반면, 프로그램 실행은 45초나 걸리던 전과는 달리 405 | 이번엔 12 초 만에 처리됩니다! 406 | 407 | 잘 보면 흥미롭게도 JIT 컴파일러가, 만델브로트 예제가 해석된 코드를 408 | 기계어로 바꿔나가는 순간을 발견할 수 있을 겁니다. 409 | 처음 몇 줄이 출력되고 난 뒤부터 프로그램이 점점 더 속도를 높여나갑니다. 410 | 411 | Tracing JIT 컴파일러에 대해서 412 | ----------------------------- 413 | Tracing JIT 컴파일러가 어떻게 돌아가는지 지금 짚고 넘어가면 좋을 것 같습니다. 414 | 간략하게 설명하자면.. 415 | 416 | 기본적으로는 여러분이 작성한 코드대로 돌아가는 인터프리터가 하나 있습니다. 417 | 그 인터프리터가 타깃 언어(BF)에서 반복되는 코드를 발견하면 해당 루프를 418 | "핫"한 지점으로 간주하고 다음부터는 추적되도록(traced) 마킹합니다. 419 | 이후에 해당 루프에 진입하게 되면 420 | 그 인터프리터는 모든 실행 명령어를 로깅하는 추적 모드로 돌아갑니다. 421 | 422 | 루프가 끝나면 추적도 멈춥니다. 추적한 내용은 최적화 공정으로 던져지고, 423 | 어셈블러를 거쳐 기계어로 나오게 됩니다. 424 | 그 기계어는 이후에 해당하는 반복 구문을 돌 때 사용됩니다. 425 | 426 | 이 기계어는 대부분의 경우에 대해서 잘 돌아가도록 최적화 되어있지만, 427 | 해석된 코드에 대해서 몇 가지 가정을 둡니다. 428 | 따라서 기계어 코드는 이 가정을 확인하기 위한 가드(guards)를 갖고 있는데요, 429 | 만약에 가드 체크가 실패하게 된다면 런타임은 430 | 본래의 해석 모드로 돌아가게(falls back) 됩니다. 431 | 432 | JIT 컴파일러에 대해서는 다음의 링크에서 더 자세히 알아볼 수 있습니다: 433 | [http://en.wikipedia.org/wiki/Just-in-time_compilation](http://en.wikipedia.org/wiki/Just-in-time_compilation) 434 | 435 | 디버깅과 로그 추적 436 | ------------------ 437 | 여기서 더 할 만한 게 있을까요? 심심한데 JIT이 뭘 하고 있는지 구경이나 해볼까요? 438 | 439 | 일단, 디버그 추적 로깅에 사용되는 `get_printable_location` 함수를 작성합시다: 440 | 441 | ```python 442 | def get_location(pc, program, bracket_map): 443 | return "%s_%s_%s" % ( 444 | program[:pc], program[pc], program[pc+1:] 445 | ) 446 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], reds=['tape'], 447 | get_printable_location=get_location) 448 | ``` 449 | 450 | 이 함수는 초록 변수들을 인자로 받아서 문자열을 반환하는 함수입니다. 451 | 이걸로 BF 코드를 밑줄로 구분해서 현재 실행하는 명령어를 볼 수 있게 출력해보죠. 452 | 453 | 이걸 [example4.py](./example4.py)로 다운받아서 example3.py 때랑 똑같이 454 | 번역해봅시다. 455 | 456 | 번역이 끝나면 테스트 프로그램(test.b 파일이고, 문자 "A"를 15번 정도 457 | 반복해서 출력하는 단순한 프로그램입니다.)을 추적 로깅하면서 돌려봅시다: 458 | 459 | ```sh 460 | $ PYPYLOG=jit-log-opt:logfile ./example4-c test.b 461 | ``` 462 | 463 | 프로그램을 돌리고 나서 "logfile" 파일을 열어봅시다. 464 | 이 파일은 꽤 읽기 어렵게 생겼군요, 이 참에 제가 설명을 좀 해보겠습니다. 465 | 466 | 이 파일은 수행된 모든 추적에 대한 로그를 담고 있어서, 467 | 여기서 무슨 명령어가 기계어로 번역되고 있는지 흘겨볼 수 있습니다. 468 | 혹시나 최적화 할 만한 위치나 불필요한 명령어가 있는지도 찾아볼 수 있죠. 469 | 470 | 각각의 추적 로그는 다음과 같은 모양의 라인으로 시작합니다: 471 | 472 | ``` 473 | [3c091099e7a4a7] {jit-log-opt-loop 474 | ``` 475 | 476 | 그리고 이런 모양으로 끝납니다: 477 | 478 | ``` 479 | [3c091099eae17d jit-log-opt-loop} 480 | ``` 481 | 482 | 그 다음 줄은 몇 번 루프인지, 몇 개의 op들로 구성됐는지를 알려줍니다. 483 | 제 경우에 첫 번째 추적 로그는 다음과 같이 생겼습니다: 484 | 485 | ``` 486 | 1 [3c167c92b9118f] {jit-log-opt-loop 487 | 2 # Loop 0 : loop with 26 ops 488 | 3 [p0, p1, i2, i3] 489 | 4 debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 490 | 5 debug_merge_point('+<[>[>_+_<-]>.[<+>-]<<-]++++++++++.', 0) 491 | 6 i4 = getarrayitem_gc(p1, i2, descr=) 492 | 7 i6 = int_add(i4, 1) 493 | 8 setarrayitem_gc(p1, i2, i6, descr=) 494 | 9 debug_merge_point('+<[>[>+_<_-]>.[<+>-]<<-]++++++++++.', 0) 495 | 10 debug_merge_point('+<[>[>+<_-_]>.[<+>-]<<-]++++++++++.', 0) 496 | 11 i7 = getarrayitem_gc(p1, i3, descr=) 497 | 12 i9 = int_sub(i7, 1) 498 | 13 setarrayitem_gc(p1, i3, i9, descr=) 499 | 14 debug_merge_point('+<[>[>+<-_]_>.[<+>-]<<-]++++++++++.', 0) 500 | 15 i10 = int_is_true(i9) 501 | 16 guard_true(i10, descr=) [p0] 502 | 17 i14 = call(ConstClass(ll_dict_lookup__dicttablePtr_Signed_Signed), ConstPtr(ptr12), 90, 90, descr=) 503 | 18 guard_no_exception(, descr=) [i14, p0] 504 | 19 i16 = int_and(i14, -9223372036854775808) 505 | 20 i17 = int_is_true(i16) 506 | 21 guard_false(i17, descr=) [i14, p0] 507 | 22 i19 = call(ConstClass(ll_get_value__dicttablePtr_Signed), ConstPtr(ptr12), i14, descr=) 508 | 23 guard_no_exception(, descr=) [i19, p0] 509 | 24 i21 = int_add(i19, 1) 510 | 25 i23 = int_lt(i21, 114) 511 | 26 guard_true(i23, descr=) [i21, p0] 512 | 27 guard_value(i21, 86, descr=) [i21, p0] 513 | 28 debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 514 | 29 jump(p0, p1, i2, i3, descr=) 515 | 30 [3c167c92bc6a15] jit-log-opt-loop} 516 | ``` 517 | 518 | `debug_merge_point` 라인들은 너무 길어서 좀 잘라냈으니 양해해주세요. 519 | 520 | 자 이게 무엇을 하는지 좀 봅시다. 네 개의 인자—두 개의 객체 포인터(`p0`, `p1`)와 521 | 두 개의 정수(`i2`, `i3`)를 받아서 추적하네요. 522 | 디버그 라인들을 보면 `[>+<-]` 반복의 한 주기를 추적하는 것 같습니다. 523 | 524 | 4번째 줄의 `>` 부터 추적이 되는데 아무것도 안 하고 즉시 다음 명령으로 넘어갑니다. 525 | `>`는 아무런 명령어도 들어가지 않고 완벽하게 최적화되어 빠져나간 것 같습니다. 526 | 이 루프는 언제나 테이프의 같은 부분에서만 돌아가야 하기 때문에 527 | 이 추적에서 테이프 포인터는 상수가 됩니다. 528 | 이 처리를 위한 명령을 명시적으로 넣어줄 필요가 없죠. 529 | 530 | 5 ~ 8번 줄에서는 `+` 명령을 위한 처리를 합니다. 531 | 먼저 포인터 `p1`이 가리키는 배열의 항목을 `i2`로 가져와서 (6번 줄), `1`을 더해서 532 | `i6`에 저장하고 (7번 줄), 그걸 다시 배열에다 저장합니다 (8번 줄). 533 | 534 | 9번 줄은 `<` 명령으로 시작하지만 이것 역시 아무런 명령어도 들어가지 않습니다. 535 | 보아하니 `i2`와 `i3`에 이 루틴의 두 테이프 포인터가 미리 계산되어 전달되는 것 같죠. 536 | 아직 `p0`이 어떤 녀석인지는 잘 모르겠지만 `p1`은 테이프 배열인 것 같습니다. 537 | 538 | 10번부터 13번 줄은 `-` 명령을 수행합니다: 배열 값을 읽어와서 (11번 줄), 539 | `1`을 빼고 (12번 줄) 배열에 값을 설정합니다 (13번 줄). 540 | 541 | 14번 줄을 보니 어느새 `]` 명령으로 도착했습니다. 542 | 15, 16번 줄에서는 `i9`가 참(`0`이 아닌 값)인지를 확인합니다. 543 | `i9`는 아까 감소시키고 저장하던 배열의 값인 것 같은데, 544 | 예상대로 반복 조건 평가에 사용되고 있네요. 545 | 16번 줄은 가드입니다. 만약 조건이 충족되지 않으면 어딘가 다른 곳으로 점프하는데, 546 | 이 경우에는 ``라고 불리는 루틴으로 `p0` 인자를 담아서 보내줍니다. 547 | 548 | 일단 가드를 통과했다고 가정하고 17번부터 23번 라인을 보면, `bracket_map`을 뒤져서 549 | 프로그램 카운터를 어디로 점프시킬지를 찾습니다. 550 | 전 사실 어떤 명령어가 실제로 무엇을 하는지 잘 모릅니다만, 551 | 딱 보아하니 뭔가 외부 호출을 두어 번 하고 가드가 세 개 있는 거 같습니다. 552 | 우리는 `bracket_map`이 절대로 바뀌지 않는다는 것을 알고 있으니 (PyPy는 이걸 모르죠) 553 | 이 부분이 꽤나 비싸뵙니다. 다음 절에서 이걸 최적화하는 법을 다룰 겁니다. 554 | 555 | 24번 줄은 새로 가져온 명령어 포인터의 값을 증가시키고, 556 | 25번과 26번 줄에서는 가져온 포인터 값이 프로그램 길이보다 작은지 확인합니다. 557 | 558 | 덧붙여 `i21`으로 가드하는 27번 줄은, 559 | 증가된 명령어 포인터의 값이 정확히 `86`인지를 검사합니다. 560 | 왜 그러냐면 이게 시작지점으로 점프했을 때 (29번 줄) 561 | 명령어 포인터 값이 `86`인 것이 이 블록의 전제조건이기 때문이죠. 562 | 563 | 마지막으로 28번 줄, 반복 주기가 종료되는 곳에서 564 | JIT은 반복을 다시 시작하는 경우를 (29번 줄) 다루기 위해 565 | 반복 몸체 ``로 점프할 수 있는데, 566 | 그때 인자들을 (`p0`, `p1`, `i2`, `i3`) 던져줍니다. 567 | 568 | 최적화 569 | ------ 570 | 모든 반복 주기는 딕셔너리 룩업으로 상응하는 괄호를 찾아서 점프한다고 얘기했었죠. 571 | 이거 상당히 비효율적입니다. 점프해서 도달할 위치는 바뀌지 않아요. 572 | 이 정보는 상수라거나 아니면 그런 무언가로 컴파일되어야 합니다. 573 | 574 | 문제는 그 룩업을 딕셔너리에서 한다는 것이고 PyPy는 그걸 불투명하게 다룬다는 것인데요. 575 | PyPy는 그 딕셔너리가 수정되지 않을거라던지 576 | 매 질의마다 다른 값을 반환하지는 않는다든지 하는 사실을 알지 못합니다. 577 | 578 | PyPy 번역기한테 이 사실을 알려주려면 579 | 딕셔너리 질의가 순수함수라는 힌트를 던져주면 됩니다. 580 | 순수함수라는 것은 반환되는 값이 *오직* 입력값에 의해서만 결정되며, 581 | 같은 입력을 던져주면 언제나 같은 값을 반환한다는 것을 의미합니다. 582 | 583 | 그렇게 하려면 제공되는 데코레이터 함수 `rpython.rlib.jit.purefunction`을 사용해서, 584 | 딕셔너리 호출을 한 번 감싸주면 됩니다: 585 | 586 | ```python 587 | @purefunction 588 | def get_matching_bracket(bracket_map, pc): 589 | return bracket_map[pc] 590 | ``` 591 | 592 | 예제 링크입니다: [example5.py](./example5.py) 593 | 594 | 다시 JIT 설정으로 변환해서 속도를 측정해봅시다. 595 | 이제 만델브로트 예제가 6초밖에 걸리지 않아요! (이 최적화를 거치기 전엔 12초가 걸렸죠) 596 | 597 | 같은 함수의 추적 로그를 다시 한 번 봅시다: 598 | 599 | ``` 600 | [3c29fad7b792b0] {jit-log-opt-loop 601 | # Loop 0 : loop with 15 ops 602 | [p0, p1, i2, i3] 603 | debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 604 | debug_merge_point('+<[>[>_+_<-]>.[<+>-]<<-]++++++++++.', 0) 605 | i4 = getarrayitem_gc(p1, i2, descr=) 606 | i6 = int_add(i4, 1) 607 | setarrayitem_gc(p1, i2, i6, descr=) 608 | debug_merge_point('+<[>[>+_<_-]>.[<+>-]<<-]++++++++++.', 0) 609 | debug_merge_point('+<[>[>+<_-_]>.[<+>-]<<-]++++++++++.', 0) 610 | i7 = getarrayitem_gc(p1, i3, descr=) 611 | i9 = int_sub(i7, 1) 612 | setarrayitem_gc(p1, i3, i9, descr=) 613 | debug_merge_point('+<[>[>+<-_]_>.[<+>-]<<-]++++++++++.', 0) 614 | i10 = int_is_true(i9) 615 | guard_true(i10, descr=) [p0] 616 | debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 617 | jump(p0, p1, i2, i3, descr=) 618 | [3c29fad7ba32ec] jit-log-opt-loop} 619 | ``` 620 | 621 | 훨씬 나아졌어요! 각 반복 주기가 더하기, 빼기, 두 번의 배열 읽기, 두 번의 배열 쓰기, 622 | 그리고 탈출 조건에 가드 한 번만 처리됩니다. 그거면 됐죠! 623 | 이 코드는 *아무런* 프로그램 카운터 조작을 필요로 하지 않습니다. 624 | 625 | 제가 딱히 최적화 전문가인 것은 아니고, 626 | 이 팁도 pypy-dev 메일링 리스트의 Armin Rigo에게서 제안된 것입니다. 627 | Carl Friedrich가 인터프리터 최적화에 대해서 작성한 일련의 포스트 또한 유용합니다: 628 | [http://bit.ly/bundles/cfbolz/1](http://bit.ly/bundles/cfbolz/1) 629 | 630 | 여담 631 | ---- 632 | 이 튜토리얼이 독자에게 633 | 빠른 파이썬 구현체로써가 아닌 PyPy에 대해 가능한 많이 보여줄 수 있었으면 합니다. 634 | 635 | PyPy가 어떻게 돌아가는지 더 알아보고 싶으신 분들을 위해, 636 | 더욱 깊은 내용을 다뤄주는 학술 논문들이 있습니다: 637 | [http://readthedocs.org/docs/pypy/en/latest/extradoc.html]([http://readthedocs.org/docs/pypy/en/latest/extradoc.html]) 638 | 639 | 전 특히 'Tracing the Meta-Level: PyPy's Tracing JIT Compiler'를 추천드립니다. 640 | -------------------------------------------------------------------------------- /bench.b: -------------------------------------------------------------------------------- 1 | *LL*LH*FF*01 2 | >++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++ 3 | [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++ 4 | ++++++++[>++++++++++[>++++++++++[>++++++++++[>+ 5 | +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++. 6 | *00 7 | -------------------------------------------------------------------------------- /bottles.b: -------------------------------------------------------------------------------- 1 | ########################## 2 | ### 3 | ### Severely updated version! 4 | ### (now says "1 bottle" and 5 | ### contains no extra "0" verse) 6 | ### 7 | ########################## 8 | ### 99 Bottles of Beer ### 9 | ### coded in Brainfuck ### 10 | ### with explanations ### 11 | ########################## 12 | # 13 | # This Bottles of Beer program 14 | # was written by Andrew Paczkowski 15 | # Coder Alias: thepacz 16 | # three_halves_plus_one@yahoo.com 17 | ##### 18 | 19 | > 0 in the zeroth cell 20 | +++++++>++++++++++[<+++++>-] 57 in the first cell or "9" 21 | +++++++>++++++++++[<+++++>-] 57 in second cell or "9" 22 | ++++++++++ 10 in third cell 23 | >+++++++++ 9 in fourth cell 24 | 25 | ########################################## 26 | ### create ASCII chars in higher cells ### 27 | ########################################## 28 | 29 | >>++++++++[<++++>-] " " 30 | >++++++++++++++[<+++++++>-] b 31 | +>+++++++++++[<++++++++++>-] o 32 | ++>+++++++++++++++++++[<++++++>-] t 33 | ++>+++++++++++++++++++[<++++++>-] t 34 | >++++++++++++[<+++++++++>-] l 35 | +>++++++++++[<++++++++++>-] e 36 | +>+++++++++++++++++++[<++++++>-] s 37 | >++++++++[<++++>-] " " 38 | +>+++++++++++[<++++++++++>-] o 39 | ++>++++++++++[<++++++++++>-] f 40 | >++++++++[<++++>-] " " 41 | >++++++++++++++[<+++++++>-] b 42 | +>++++++++++[<++++++++++>-] e 43 | +>++++++++++[<++++++++++>-] e 44 | >+++++++++++++++++++[<++++++>-] r 45 | >++++++++[<++++>-] " " 46 | +>+++++++++++[<++++++++++>-] o 47 | >+++++++++++[<++++++++++>-] n 48 | >++++++++[<++++>-] " " 49 | ++>+++++++++++++++++++[<++++++>-] t 50 | ++++>++++++++++[<++++++++++>-] h 51 | +>++++++++++[<++++++++++>-] e 52 | >++++++++[<++++>-] " " 53 | ++>+++++++++++++[<+++++++++>-] w 54 | +>++++++++++++[<++++++++>-] a 55 | >++++++++++++[<+++++++++>-] l 56 | >++++++++++++[<+++++++++>-] l 57 | >+++++[<++>-] LF 58 | ++>+++++++++++++++++++[<++++++>-] t 59 | +>++++++++++++[<++++++++>-] a 60 | +++>+++++++++++++[<++++++++>-] k 61 | +>++++++++++[<++++++++++>-] e 62 | >++++++++[<++++>-] " " 63 | +>+++++++++++[<++++++++++>-] o 64 | >+++++++++++[<++++++++++>-] n 65 | +>++++++++++[<++++++++++>-] e 66 | >++++++++[<++++>-] " " 67 | >++++++++++[<++++++++++>-] d 68 | +>+++++++++++[<++++++++++>-] o 69 | ++>+++++++++++++[<+++++++++>-] w 70 | >+++++++++++[<++++++++++>-] n 71 | >++++++++[<++++>-] " " 72 | +>++++++++++++[<++++++++>-] a 73 | >+++++++++++[<++++++++++>-] n 74 | >++++++++++[<++++++++++>-] d 75 | >++++++++[<++++>-] " " 76 | ++>+++++++++++[<++++++++++>-] p 77 | +>++++++++++++[<++++++++>-] a 78 | +>+++++++++++++++++++[<++++++>-] s 79 | +>+++++++++++++++++++[<++++++>-] s 80 | >++++++++[<++++>-] " " 81 | +>+++++++++++++[<++++++++>-] i 82 | ++>+++++++++++++++++++[<++++++>-] t 83 | >++++++++[<++++>-] " " 84 | +>++++++++++++[<++++++++>-] a 85 | >+++++++++++++++++++[<++++++>-] r 86 | +>+++++++++++[<++++++++++>-] o 87 | >+++++++++++++[<+++++++++>-] u 88 | >+++++++++++[<++++++++++>-] n 89 | >++++++++++[<++++++++++>-] d 90 | >+++++[<++>-] LF 91 | +++++++++++++ CR 92 | 93 | [<]>>>> go back to fourth cell 94 | 95 | ################################# 96 | ### initiate the display loop ### 97 | ################################# 98 | 99 | [ loop 100 | < back to cell 3 101 | [ loop 102 | [>]<< go to last cell and back to LF 103 | .. output 2 newlines 104 | [<]> go to first cell 105 | 106 | ################################### 107 | #### begin display of characters### 108 | ################################### 109 | # 110 | #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 111 | #X X b o t t l e s o f b e e r 112 | #.>.>.>.>.>.>.>.>.>.>.>. 113 | #o n t h e w a l l N 114 | #[<]> go to first cell 115 | #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.> 116 | #X X b o t t l e s o f b e e r N 117 | #.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 118 | #t a k e o n e d o w n a n d p a s s 119 | #.>.>.>.>.>.>.>.>.>. 120 | #i t a r o u n d N 121 | ##### 122 | 123 | [<]>> go to cell 2 124 | - subtract 1 from cell 2 125 | < go to cell 1 126 | 127 | ######################## 128 | ### display last line ## 129 | ######################## 130 | # 131 | #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 132 | #X X b o t t l e s o f b e e r 133 | #.>.>.>.>.>.>.>.>.>.>. 134 | #o n t h e w a l l 135 | ##### 136 | 137 | [<]>>>- go to cell 3/subtract 1 138 | ] end loop when cell 3 is 0 139 | ++++++++++ add 10 to cell 3 140 | <++++++++++ back to cell 2/add 10 141 | <- back to cell 1/subtract 1 142 | [>]<. go to last line/carriage return 143 | [<]> go to first line 144 | 145 | ######################## 146 | ### correct last line ## 147 | ######################## 148 | # 149 | #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 150 | #X X b o t t l e s o f b e e r 151 | #.>.>.>.>.>.>.>.>.>.>. 152 | #o n t h e w a l l 153 | ##### 154 | 155 | [<]>>>>- go to cell 4/subtract 1 156 | ] end loop when cell 4 is 0 157 | 158 | ############################################################## 159 | ### By this point verses 99\10 are displayed but to work ### 160 | ### with the lower numbered verses in a more readable way ### 161 | ### we initiate a new loop for verses 9\0 that will not ### 162 | ### use the fourth cell at all ### 163 | ############################################################## 164 | 165 | + add 1 to cell four (to keep it non\zero) 166 | <-- back to cell 3/subtract 2 167 | 168 | [ loop 169 | [>]<< go to last cell and back to LF 170 | .. output 2 newlines 171 | [<]> go to first cell 172 | 173 | ################################### 174 | #### begin display of characters### 175 | ################################### 176 | # 177 | #>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 178 | # X b o t t l e s o f b e e r 179 | #.>.>.>.>.>.>.>.>.>.>.>. 180 | #o n t h e w a l l N 181 | #[<]> go to first cell 182 | #>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.> 183 | # X b o t t l e s o f b e e r N 184 | #.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 185 | #t a k e o n e d o w n a n d p a s s 186 | #.>.>.>.>.>.>.>.>.>. 187 | #i t a r o u n d N 188 | ##### 189 | 190 | [<]>> go to cell 2 191 | - subtract 1 from cell 2 192 | 193 | ######################## 194 | ### display last line ## 195 | ######################## 196 | # 197 | #.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 198 | #X b o t t l e s o f b e e r 199 | #.>.>.>.>.>.>.>.>.>.>. 200 | #o n t h e w a l l 201 | ##### 202 | 203 | [<]>>>- go to cell 3/subtract 1 204 | ] end loop when cell 3 is 0 205 | + add 1 to cell 3 to keep it non\zero 206 | 207 | [>]<. go to last line/carriage return 208 | [<]> go to first line 209 | 210 | ######################## 211 | ### correct last line ## 212 | ######################## 213 | # 214 | #>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>.> 215 | # X b o t t l e o f b e e r 216 | #.>.>.>.>.>.>.>.>.>.>.<<<<. 217 | #o n t h e w a l l 218 | ##### 219 | 220 | [>]<< go to last cell and back to LF 221 | .. output 2 newlines 222 | [<]> go to first line 223 | 224 | ######################### 225 | ### the final verse ## 226 | ######################### 227 | # 228 | #>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>.> 229 | # X b o t t l e o f b e e r 230 | #.>.>.>.>.>.>.>.>.>.>.>. 231 | #o n t h e w a l l N 232 | #[<]> go to first cell 233 | #>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.> 234 | # X b o t t l e o f b e e r N 235 | #.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 236 | #t a k e o n e d o w n a n d p a s s 237 | #.>.>.>.>.>.>.>.>.>. 238 | #i t a r o u n d N 239 | #[>]< go to last line 240 | #<<<.<<.<<<. 241 | # n o 242 | #[<]>>>> go to fourth cell 243 | #>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> 244 | # b o t t l e s o f b e e r 245 | #.>.>.>.>.>.>.>.>.>.>.>. 246 | #o n t h e w a l l N 247 | #####fin## -------------------------------------------------------------------------------- /example1.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyPy tutorial by Andrew Brown 3 | example1.py - Python BF interpreter 4 | 5 | """ 6 | 7 | def mainloop(program, bracket_map): 8 | pc = 0 9 | tape = Tape() 10 | 11 | while pc < len(program): 12 | 13 | code = program[pc] 14 | 15 | if code == ">": 16 | tape.advance() 17 | 18 | elif code == "<": 19 | tape.devance() 20 | 21 | elif code == "+": 22 | tape.inc() 23 | 24 | elif code == "-": 25 | tape.dec() 26 | 27 | elif code == ".": 28 | # print 29 | sys.stdout.write(chr(tape.get())) 30 | 31 | elif code == ",": 32 | # read from stdin 33 | tape.set(ord(sys.stdin.read(1))) 34 | 35 | elif code == "[" and tape.get() == 0: 36 | # Skip forward to the matching ] 37 | pc = bracket_map[pc] 38 | 39 | elif code == "]" and tape.get() != 0: 40 | # Skip back to the matching [ 41 | pc = bracket_map[pc] 42 | 43 | pc += 1 44 | 45 | class Tape(object): 46 | def __init__(self): 47 | self.thetape = [0] 48 | self.position = 0 49 | 50 | def get(self): 51 | return self.thetape[self.position] 52 | def set(self, val): 53 | self.thetape[self.position] = val 54 | def inc(self): 55 | self.thetape[self.position] += 1 56 | def dec(self): 57 | self.thetape[self.position] -= 1 58 | def advance(self): 59 | self.position += 1 60 | if len(self.thetape) <= self.position: 61 | self.thetape.append(0) 62 | def devance(self): 63 | self.position -= 1 64 | 65 | def parse(program): 66 | parsed = [] 67 | bracket_map = {} 68 | leftstack = [] 69 | 70 | pc = 0 71 | for char in program: 72 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 73 | parsed.append(char) 74 | 75 | if char == '[': 76 | leftstack.append(pc) 77 | elif char == ']': 78 | left = leftstack.pop() 79 | right = pc 80 | bracket_map[left] = right 81 | bracket_map[right] = left 82 | pc += 1 83 | 84 | return "".join(parsed), bracket_map 85 | 86 | def run(input): 87 | program, map = parse(input.read()) 88 | mainloop(program, map) 89 | 90 | if __name__ == "__main__": 91 | import sys 92 | run(open(sys.argv[1], 'r')) 93 | -------------------------------------------------------------------------------- /example2.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyPy tutorial by Andrew Brown 3 | example2.py - BF interpreter in RPython, translatable by PyPy 4 | 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | def mainloop(program, bracket_map): 11 | pc = 0 12 | tape = Tape() 13 | 14 | while pc < len(program): 15 | 16 | code = program[pc] 17 | 18 | if code == ">": 19 | tape.advance() 20 | 21 | elif code == "<": 22 | tape.devance() 23 | 24 | elif code == "+": 25 | tape.inc() 26 | 27 | elif code == "-": 28 | tape.dec() 29 | 30 | elif code == ".": 31 | # print 32 | os.write(1, chr(tape.get())) 33 | 34 | elif code == ",": 35 | # read from stdin 36 | tape.set(ord(os.read(0, 1)[0])) 37 | 38 | elif code == "[" and tape.get() == 0: 39 | # Skip forward to the matching ] 40 | pc = bracket_map[pc] 41 | 42 | elif code == "]" and tape.get() != 0: 43 | # Skip back to the matching [ 44 | pc = bracket_map[pc] 45 | 46 | pc += 1 47 | 48 | class Tape(object): 49 | def __init__(self): 50 | self.thetape = [0] 51 | self.position = 0 52 | 53 | def get(self): 54 | return self.thetape[self.position] 55 | def set(self, val): 56 | self.thetape[self.position] = val 57 | def inc(self): 58 | self.thetape[self.position] += 1 59 | def dec(self): 60 | self.thetape[self.position] -= 1 61 | def advance(self): 62 | self.position += 1 63 | if len(self.thetape) <= self.position: 64 | self.thetape.append(0) 65 | def devance(self): 66 | self.position -= 1 67 | 68 | def parse(program): 69 | parsed = [] 70 | bracket_map = {} 71 | leftstack = [] 72 | 73 | pc = 0 74 | for char in program: 75 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 76 | parsed.append(char) 77 | 78 | if char == '[': 79 | leftstack.append(pc) 80 | elif char == ']': 81 | left = leftstack.pop() 82 | right = pc 83 | bracket_map[left] = right 84 | bracket_map[right] = left 85 | pc += 1 86 | 87 | return "".join(parsed), bracket_map 88 | 89 | def run(fp): 90 | program_contents = "" 91 | while True: 92 | read = os.read(fp, 4096) 93 | if len(read) == 0: 94 | break 95 | program_contents += read 96 | os.close(fp) 97 | program, bm = parse(program_contents) 98 | mainloop(program, bm) 99 | 100 | def entry_point(argv): 101 | try: 102 | filename = argv[1] 103 | except IndexError: 104 | print "You must supply a filename" 105 | return 1 106 | 107 | run(os.open(filename, os.O_RDONLY, 0777)) 108 | return 0 109 | 110 | def target(*args): 111 | return entry_point, None 112 | 113 | if __name__ == "__main__": 114 | entry_point(sys.argv) 115 | -------------------------------------------------------------------------------- /example3.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyPy tutorial by Andrew Brown 3 | example3.py - BF interpreter in RPython, translatable by PyPy, with JIT 4 | 5 | """ 6 | 7 | import os 8 | import sys 9 | 10 | # So that you can still run this module under standard CPython, I add this 11 | # import guard that creates a dummy class instead. 12 | try: 13 | from rpython.rlib.jit import JitDriver 14 | except ImportError: 15 | class JitDriver(object): 16 | def __init__(self,**kw): pass 17 | def jit_merge_point(self,**kw): pass 18 | def can_enter_jit(self,**kw): pass 19 | 20 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], reds=['tape']) 21 | 22 | def mainloop(program, bracket_map): 23 | pc = 0 24 | tape = Tape() 25 | 26 | while pc < len(program): 27 | jitdriver.jit_merge_point(pc=pc, tape=tape, program=program, 28 | bracket_map=bracket_map) 29 | 30 | code = program[pc] 31 | 32 | if code == ">": 33 | tape.advance() 34 | 35 | elif code == "<": 36 | tape.devance() 37 | 38 | elif code == "+": 39 | tape.inc() 40 | 41 | elif code == "-": 42 | tape.dec() 43 | 44 | elif code == ".": 45 | # print 46 | os.write(1, chr(tape.get())) 47 | 48 | elif code == ",": 49 | # read from stdin 50 | tape.set(ord(os.read(0, 1)[0])) 51 | 52 | elif code == "[" and tape.get() == 0: 53 | # Skip forward to the matching ] 54 | pc = bracket_map[pc] 55 | 56 | elif code == "]" and tape.get() != 0: 57 | # Skip back to the matching [ 58 | pc = bracket_map[pc] 59 | 60 | pc += 1 61 | 62 | class Tape(object): 63 | def __init__(self): 64 | self.thetape = [0] 65 | self.position = 0 66 | 67 | def get(self): 68 | return self.thetape[self.position] 69 | def set(self, val): 70 | self.thetape[self.position] = val 71 | def inc(self): 72 | self.thetape[self.position] += 1 73 | def dec(self): 74 | self.thetape[self.position] -= 1 75 | def advance(self): 76 | self.position += 1 77 | if len(self.thetape) <= self.position: 78 | self.thetape.append(0) 79 | def devance(self): 80 | self.position -= 1 81 | 82 | def parse(program): 83 | parsed = [] 84 | bracket_map = {} 85 | leftstack = [] 86 | 87 | pc = 0 88 | for char in program: 89 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 90 | parsed.append(char) 91 | 92 | if char == '[': 93 | leftstack.append(pc) 94 | elif char == ']': 95 | left = leftstack.pop() 96 | right = pc 97 | bracket_map[left] = right 98 | bracket_map[right] = left 99 | pc += 1 100 | 101 | return "".join(parsed), bracket_map 102 | 103 | def run(fp): 104 | program_contents = "" 105 | while True: 106 | read = os.read(fp, 4096) 107 | if len(read) == 0: 108 | break 109 | program_contents += read 110 | os.close(fp) 111 | program, bm = parse(program_contents) 112 | mainloop(program, bm) 113 | 114 | def entry_point(argv): 115 | try: 116 | filename = argv[1] 117 | except IndexError: 118 | print "You must supply a filename" 119 | return 1 120 | 121 | run(os.open(filename, os.O_RDONLY, 0777)) 122 | return 0 123 | 124 | def target(*args): 125 | return entry_point, None 126 | 127 | def jitpolicy(driver): 128 | from rpython.jit.codewriter.policy import JitPolicy 129 | return JitPolicy() 130 | 131 | if __name__ == "__main__": 132 | entry_point(sys.argv) 133 | -------------------------------------------------------------------------------- /example4.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyPy tutorial by Andrew Brown 3 | example4.py - BF interpreter in RPython, translatable by PyPy, with JIT, and 4 | with a get_printable_location function 5 | 6 | """ 7 | 8 | import os 9 | import sys 10 | 11 | # So that you can still run this module under standard CPython, I add this 12 | # import guard that creates a dummy class instead. 13 | try: 14 | from rpython.rlib.jit import JitDriver 15 | except ImportError: 16 | class JitDriver(object): 17 | def __init__(self,**kw): pass 18 | def jit_merge_point(self,**kw): pass 19 | def can_enter_jit(self,**kw): pass 20 | 21 | def get_location(pc, program, bracket_map): 22 | return "%s_%s_%s" % ( 23 | program[:pc], program[pc], program[pc+1:] 24 | ) 25 | 26 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], reds=['tape'], 27 | get_printable_location=get_location) 28 | 29 | def mainloop(program, bracket_map): 30 | pc = 0 31 | tape = Tape() 32 | 33 | while pc < len(program): 34 | jitdriver.jit_merge_point(pc=pc, tape=tape, program=program, 35 | bracket_map=bracket_map) 36 | 37 | code = program[pc] 38 | 39 | if code == ">": 40 | tape.advance() 41 | 42 | elif code == "<": 43 | tape.devance() 44 | 45 | elif code == "+": 46 | tape.inc() 47 | 48 | elif code == "-": 49 | tape.dec() 50 | 51 | elif code == ".": 52 | # print 53 | os.write(1, chr(tape.get())) 54 | 55 | elif code == ",": 56 | # read from stdin 57 | tape.set(ord(os.read(0, 1)[0])) 58 | 59 | elif code == "[" and tape.get() == 0: 60 | # Skip forward to the matching ] 61 | pc = bracket_map[pc] 62 | 63 | elif code == "]" and tape.get() != 0: 64 | # Skip back to the matching [ 65 | pc = bracket_map[pc] 66 | 67 | pc += 1 68 | 69 | class Tape(object): 70 | def __init__(self): 71 | self.thetape = [0] 72 | self.position = 0 73 | 74 | def get(self): 75 | return self.thetape[self.position] 76 | def set(self, val): 77 | self.thetape[self.position] = val 78 | def inc(self): 79 | self.thetape[self.position] += 1 80 | def dec(self): 81 | self.thetape[self.position] -= 1 82 | def advance(self): 83 | self.position += 1 84 | if len(self.thetape) <= self.position: 85 | self.thetape.append(0) 86 | def devance(self): 87 | self.position -= 1 88 | 89 | def parse(program): 90 | parsed = [] 91 | bracket_map = {} 92 | leftstack = [] 93 | 94 | pc = 0 95 | for char in program: 96 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 97 | parsed.append(char) 98 | 99 | if char == '[': 100 | leftstack.append(pc) 101 | elif char == ']': 102 | left = leftstack.pop() 103 | right = pc 104 | bracket_map[left] = right 105 | bracket_map[right] = left 106 | pc += 1 107 | 108 | return "".join(parsed), bracket_map 109 | 110 | def run(fp): 111 | program_contents = "" 112 | while True: 113 | read = os.read(fp, 4096) 114 | if len(read) == 0: 115 | break 116 | program_contents += read 117 | os.close(fp) 118 | program, bm = parse(program_contents) 119 | mainloop(program, bm) 120 | 121 | def entry_point(argv): 122 | try: 123 | filename = argv[1] 124 | except IndexError: 125 | print "You must supply a filename" 126 | return 1 127 | 128 | run(os.open(filename, os.O_RDONLY, 0777)) 129 | return 0 130 | 131 | def target(*args): 132 | return entry_point, None 133 | 134 | def jitpolicy(driver): 135 | from rpython.jit.codewriter.policy import JitPolicy 136 | return JitPolicy() 137 | 138 | if __name__ == "__main__": 139 | entry_point(sys.argv) 140 | -------------------------------------------------------------------------------- /example5.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyPy tutorial by Andrew Brown 3 | example5.py - BF interpreter in RPython, translatable by PyPy, with JIT, and 4 | with a get_printable_location function and pure function wrapper 5 | for the dictionary lookup. 6 | 7 | """ 8 | 9 | import os 10 | import sys 11 | 12 | # So that you can still run this module under standard CPython, I add this 13 | # import guard that creates a dummy class instead. 14 | try: 15 | from rpython.rlib.jit import JitDriver, purefunction 16 | except ImportError: 17 | class JitDriver(object): 18 | def __init__(self,**kw): pass 19 | def jit_merge_point(self,**kw): pass 20 | def can_enter_jit(self,**kw): pass 21 | def purefunction(f): return f 22 | 23 | def get_location(pc, program, bracket_map): 24 | return "%s_%s_%s" % ( 25 | program[:pc], program[pc], program[pc+1:] 26 | ) 27 | 28 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], reds=['tape'], 29 | get_printable_location=get_location) 30 | 31 | @purefunction 32 | def get_matching_bracket(bracket_map, pc): 33 | return bracket_map[pc] 34 | 35 | def mainloop(program, bracket_map): 36 | pc = 0 37 | tape = Tape() 38 | 39 | while pc < len(program): 40 | jitdriver.jit_merge_point(pc=pc, tape=tape, program=program, 41 | bracket_map=bracket_map) 42 | 43 | code = program[pc] 44 | 45 | if code == ">": 46 | tape.advance() 47 | 48 | elif code == "<": 49 | tape.devance() 50 | 51 | elif code == "+": 52 | tape.inc() 53 | 54 | elif code == "-": 55 | tape.dec() 56 | 57 | elif code == ".": 58 | # print 59 | os.write(1, chr(tape.get())) 60 | 61 | elif code == ",": 62 | # read from stdin 63 | tape.set(ord(os.read(0, 1)[0])) 64 | 65 | elif code == "[" and tape.get() == 0: 66 | # Skip forward to the matching ] 67 | pc = get_matching_bracket(bracket_map, pc) 68 | 69 | elif code == "]" and tape.get() != 0: 70 | # Skip back to the matching [ 71 | pc = get_matching_bracket(bracket_map, pc) 72 | 73 | pc += 1 74 | 75 | class Tape(object): 76 | def __init__(self): 77 | self.thetape = [0] 78 | self.position = 0 79 | 80 | def get(self): 81 | return self.thetape[self.position] 82 | def set(self, val): 83 | self.thetape[self.position] = val 84 | def inc(self): 85 | self.thetape[self.position] += 1 86 | def dec(self): 87 | self.thetape[self.position] -= 1 88 | def advance(self): 89 | self.position += 1 90 | if len(self.thetape) <= self.position: 91 | self.thetape.append(0) 92 | def devance(self): 93 | self.position -= 1 94 | 95 | def parse(program): 96 | parsed = [] 97 | bracket_map = {} 98 | leftstack = [] 99 | 100 | pc = 0 101 | for char in program: 102 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 103 | parsed.append(char) 104 | 105 | if char == '[': 106 | leftstack.append(pc) 107 | elif char == ']': 108 | left = leftstack.pop() 109 | right = pc 110 | bracket_map[left] = right 111 | bracket_map[right] = left 112 | pc += 1 113 | 114 | return "".join(parsed), bracket_map 115 | 116 | def run(fp): 117 | program_contents = "" 118 | while True: 119 | read = os.read(fp, 4096) 120 | if len(read) == 0: 121 | break 122 | program_contents += read 123 | os.close(fp) 124 | program, bm = parse(program_contents) 125 | mainloop(program, bm) 126 | 127 | def entry_point(argv): 128 | try: 129 | filename = argv[1] 130 | except IndexError: 131 | print "You must supply a filename" 132 | return 1 133 | 134 | run(os.open(filename, os.O_RDONLY, 0777)) 135 | return 0 136 | 137 | def target(*args): 138 | return entry_point, None 139 | 140 | def jitpolicy(driver): 141 | from rpython.jit.codewriter.policy import JitPolicy 142 | return JitPolicy() 143 | 144 | if __name__ == "__main__": 145 | entry_point(sys.argv) 146 | -------------------------------------------------------------------------------- /hanoi.b: -------------------------------------------------------------------------------- 1 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>> 3 | >>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>> 4 | >>>>>>>>>>>>>>>>>>>>>>>>>[-]>[-]+++++++++++++++++++++++++++.++++++++++++++++ 5 | ++++++++++++++++++++++++++++++++++++++++++++++++.-------------------.------- 6 | --------------------------------------.+++++++++++++++++++++++++++++++++++++ 7 | +++++++++++++++++++++++++++.-----------------------------------------.++++++ 8 | ++++++++++++++++++.[-]+++++++++++++++++++++++++++.++++++++++++++++++++++++++ 9 | ++++++++++++++++++++++++++++++++++++++.------------------------------------- 10 | ----.+++++++++.---------.+++++.+++++++++++++++++.++++++++++++.++++++++++++++ 11 | +++++++++++++.++++++++.------------------.+++++++++++++.+.------------------ 12 | -----------------------------------------------------------------.++++++++++ 13 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------ 14 | ---.----------------------------------------------------------------------.+ 15 | +++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++.++++++++++ 16 | +++.+.------.--------------------------------------------------------------- 17 | ----------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 18 | ++++++++.+++++.------------------------------------------------------------- 19 | -----------------.++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++ 20 | +++++++++++++++++++++++++.-----------------.++++++++.+++++.--------.-------- 21 | ----------------------------------------------------.+++++++++++++++++++++++ 22 | ++++++++++++++++++++++++++++++++++.++++++++.[-]+++++++++++++++++++++++++++.+ 23 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------------ 24 | ----------------------------.++++++++.----------.++++.+++++++++++++++++++.++ 25 | +++++++++++++.+++++++++++++++++++++++++++.---------.+++++++++++..----------- 26 | ----.+++++++++.------------------------------------------------------------- 27 | -----------------.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 28 | ++++++++.+++++++++++++++++++++++.------------------------------------------- 29 | ----------------------------------------------.+++++++++++++++++++++++++++++ 30 | ++++++.+++++++++++++++++++++++++++++++++++++++++.---.---..+++++++++.+++.---- 31 | ----------.----------------------------------------------------------------- 32 | ---.+++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++ 33 | ++++++++.---.------.-------------------------------------------------------- 34 | --------------.++++++++++++++++++++++++++++.++++++++++++++++++++++++++++++++ 35 | ++++++++++++.++++++++++++..----.-------------------------------------------- 36 | ----------.-----------..++++++++++++++++++++++++++++++++++++++++++++++++++++ 37 | ++++++++++++++++++++...----------------------------------------------------- 38 | --------------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++.+ 39 | ++++++++.---.---..+++++++++.+++.--------------.----------------------------- 40 | -------------------------.++++++++++++++++++++++++++++++++++++++++++++++++++ 41 | +.+++++++++++++++++++.------------------------------------------------------ 42 | ---------------.+++++++++++++++++++++++++++++++++++++++++++++++++++.++++.--- 43 | .+++++++++++++.+++++.------------------------------------------------------- 44 | ---------------.+++++++++++++++.[-]>[-]+++++++++>[-]+++>>[-]>[-]<<<<<[->>>>> 45 | +<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<< 46 | <+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<] 47 | >>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[- 48 | <<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-]++++++++++++++++++++++ 49 | +++++++++++++++++++++++>[-]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<+++++++++ 50 | ++++++++++++++++++++++++++++++++++>]<<<[>>>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<< 51 | ->>>][-]++++++++++++++++>[-]++++++++++++++>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<< 52 | <<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[ 53 | [-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+ 54 | <<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]> 55 | >[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[- 56 | ]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>> 57 | >[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]< 58 | ]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<< 59 | [-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<< 60 | [[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+ 61 | >>>>>>>>][-]+++++++++++++++++++++++++<<<[-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-] 62 | [-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<< 63 | <+>>>>->>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>->>>>]>[-] 64 | >[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[- 65 | ]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+ 66 | >>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>> 67 | >]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>> 68 | ]<<<[[-]<<<<----->>>>][-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<< 69 | +>>>>>>->>>][-]+++++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++ 70 | +++++++++++++++++++++++++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>> 71 | >>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[ 72 | -]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-> 73 | >>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<< 74 | +>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<] 75 | >[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]< 76 | <<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->> 77 | +<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]> 78 | >>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[ 79 | -]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]> 80 | ]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+ 81 | +++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[- 82 | <<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[-> 83 | >>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<< 84 | [-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>> 85 | ]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>> 86 | >[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-] 87 | <<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[ 88 | [-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>> 89 | [[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+< 90 | <<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>> 91 | >+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>-> 92 | [-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-] 93 | +>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[ 94 | -<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<< 95 | <<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+> 96 | >>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<< 97 | <<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[- 98 | >>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<+++ 99 | +++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++ 100 | +++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-< 101 | ]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++++++++++++++++++ 102 | +++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++. 103 | >>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>] 104 | <<]<<<<<<--------------------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>> 105 | >>[-<+<<<<<+>>>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++ 106 | +++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<< 107 | +>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+ 108 | <<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-] 109 | >>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>> 110 | >>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]> 111 | >>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[ 112 | -]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>> 113 | >[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<] 114 | >>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-< 115 | +<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[-> 116 | >>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->> 117 | ->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[ 118 | -]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>> 119 | >>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++ 120 | +++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[ 121 | [-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[ 122 | ->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+ 123 | >[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+ 124 | <<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>] 125 | [-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-] 126 | +>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>> 127 | [[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[- 128 | <<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>] 129 | [-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<< 130 | <<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]> 131 | [-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>] 132 | <]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>> 133 | [-]+<[[-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++ 134 | +++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++++++++ 135 | +++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++ 136 | +++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++ 137 | +++++++++++++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++ 138 | ++++++++.>>>>>>]<<]<<<<<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>> 139 | >>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++++++++++++++++++++++ 140 | +++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+ 141 | >>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>> 142 | >[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<< 143 | +>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]++++++++++++++++++ 144 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 145 | ++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<[->>>>>>>>+<<< 146 | <<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<.. 147 | >>>-]<<<.>>>>>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>> 148 | ][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[->>>>>>>+<<<<< 149 | <<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]++++++++++++++++++++++++++++++++++++++++++++ 150 | ++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>> 151 | [[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>> 152 | +<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<] 153 | >>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++ 154 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 155 | +++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<<<]>>>[-]<<<< 156 | <[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<<<<<<<[-]<[-]<[-]>>>>>>>>>>[-]<<<<<[->>> 157 | >>+<<<<<]>>>>>[-<<<<<+<<<+>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 158 | <<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<< 159 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 160 | >>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>> 161 | >>>>>>>>>>>>>>>>>>>>+>>>>>>>>>]<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<- 162 | [<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 163 | <<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>+<<<< 164 | <]>>>>>[[-<<<<<+>>>>>]<<<<<->>>>>]<]<<<<<+>>[-]+>>[-]>[-]<<<<<[->>>>>+<<<<<] 165 | >>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]> 166 | [-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-< 167 | <<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]< 168 | <<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<]<<<[-]>[-]+>[-]++>[-]++++++++>[-] 169 | +>[-]+[>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++<<[-]>>>[-]>[ 170 | -]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<- 171 | >->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>> 172 | ]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[- 173 | ]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]>[-]>[-]>[-]>>[-]>[-]<<<<<<<<<<[->>> 174 | >>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<< 175 | <[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[ 176 | -]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]< 177 | ][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-] 178 | +>[-]+>>]>[-]>[-]<<<<<<<<<<[->>>>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+> 179 | >>>>>>>>>][-]+++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<] 180 | >>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[- 181 | >>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[-> 182 | +<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]+>>[-]+>][-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[- 183 | ]>>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>[-]>[-< 184 | <<<<<<<<<<<<<<+>>>>>>>>>>>>>>+>]<[<+>-]>[-]<<<<<<<<<<<<<<[->>>>>>>>>>>>>>+<< 185 | <<<<<<<<<<<<]>>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>]<[<+++>-]>[-] 186 | <<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<+> 187 | >>>>>>>>>>>+>]<[<+++++++++>-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 188 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 189 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 190 | <<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 191 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 192 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 193 | >>>>>>>>>>>>>>>>>>>>>>>>>[-]<<[->>+<<]>>[-<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 194 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 195 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 196 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 197 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 198 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 199 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<< 200 | <<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 201 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 202 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 203 | <<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 204 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 205 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 206 | >>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 207 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 208 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 209 | <<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>> 210 | >-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>> 211 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 212 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 213 | >>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<<<<<<<]>>>>>>>>>>>>[-< 214 | <<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 215 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 216 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 217 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 218 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<< 219 | <[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<< 220 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 221 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 222 | <<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 223 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 224 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 225 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 226 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-] 227 | <[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>> 228 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>> 229 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 230 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<< 231 | <<]>>>>>>>>>>>[-<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 232 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 233 | <<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 234 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<< 235 | <<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<< 236 | <<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 237 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>> 238 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 239 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<< 240 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 241 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[< 242 | <<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 243 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 244 | >>>>>>>>>>>>>>>+>>>>>>>>>>>>>][-]<<[->>+<<]>>[[-<<+>>]>[-]<<<<<<<<<<<<[->>>> 245 | >>>>>>>>+<<<<<<<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<< 246 | <<<<[->>>>>>>>>>>+<<<<<<<<<<<]<[-]>>>>>>>>>>>>[-<<<<<<<<<<<+<+>>>>>>>>>>>>][ 247 | -]<<<<<<<[->>>>>>>+<<<<<<<]<<<<[-]>>>>>>>>>>>[-<<<<<<<+<<<<+>>>>>>>>>>>]<<<< 248 | <<<<<<->[-]>+>>>>>>>][-]<[->+<]>[[-<+>]>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<< 249 | <<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<<<<<<<[->>>>>>> 250 | >>>>>>+<<<<<<<<<<<<<]>[-]>>>>>>>>>>>>[-<<<<<<<<<<<<<+>+>>>>>>>>>>>>][-]<<<<< 251 | <<[->>>>>>>+<<<<<<<]<<<<<<[-]>>>>>>>>>>>>>[-<<<<<<<+<<<<<<+>>>>>>>>>>>>>]<<< 252 | <<<<<<<->[-]>+>>>>>>>]<<<<]>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>> 253 | >>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-< 254 | <<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<< 255 | ]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[- 256 | <+>]<<<[-]>>>]<<<[[-]>>>>[-]++>>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<< 257 | <<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[- 258 | ]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[ 259 | <<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-] 260 | +>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[- 261 | ]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>> 262 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 263 | <<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 264 | >[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>> 265 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[- 266 | >>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>> 267 | >>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[- 268 | <<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<< 269 | <]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[ 270 | -<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 271 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 272 | <<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 273 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 274 | +<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 275 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>> 276 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 277 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<< 278 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 279 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 280 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 281 | >>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<< 282 | <<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[-]+>> 283 | >[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]< 284 | ]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<< 285 | [-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<< 286 | [[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 287 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 288 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<< 289 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]> 290 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 291 | >>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 292 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 293 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-] 294 | >[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<< 295 | <<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[- 296 | ]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<< 297 | +>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<< 298 | [-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 299 | <<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>> 300 | >>>>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 301 | <[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<< 302 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 303 | >>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 304 | <<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<< 305 | <<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+ 306 | <<<<]<<>>>>]>>[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<< 307 | <<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>> 308 | >>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]> 309 | >>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-> 310 | >>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+ 311 | <]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 312 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 313 | <<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>> 314 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 315 | >>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 316 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 317 | <<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 318 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<< 319 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 320 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>> 321 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 322 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 323 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 324 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>> 325 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 326 | >>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 327 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-] 328 | <<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>> 329 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<< 330 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 331 | <<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 332 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>> 333 | >+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[ 334 | -]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-] 335 | +>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+> 336 | >>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>> 337 | >]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 338 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[- 339 | ]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>[-]<<<<<< 340 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 341 | <<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 342 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 343 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>> 344 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 345 | >>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 346 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>> 347 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<< 348 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<< 349 | [->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>> 350 | >>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 351 | <]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<< 352 | <<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>> 353 | >][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+> 354 | >>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>> 355 | [[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>] 356 | <<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>> 357 | +<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<+>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<< 358 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 359 | >>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>> 360 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<< 361 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+> 362 | >>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+ 363 | >>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 364 | <+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<< 365 | <<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>> 366 | ][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+> 367 | >>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>> 368 | [[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>] 369 | <<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 370 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>> 371 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-] 372 | <<<<<[->>>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 373 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>> 374 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-] 375 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 376 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>> 377 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 378 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<< 379 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 380 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 381 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 382 | >>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 383 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 384 | <<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>> 385 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 386 | ]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 387 | <<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<< 388 | ]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>> 389 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 390 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[ 391 | ->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-] 392 | ++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>] 393 | <<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[- 394 | <<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<< 395 | [-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[- 396 | ]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->> 397 | >>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+ 398 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<< 399 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 400 | <<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 401 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 402 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>> 403 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-< 404 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 405 | <<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>> 406 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 407 | <<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<< 408 | <<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>> 409 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 410 | >>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>> 411 | >>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+ 412 | >>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>> 413 | >[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<< 414 | +>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<< 415 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 416 | >>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>> 417 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<< 418 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 419 | >>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>> 420 | >>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]> 421 | >>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[-> 422 | >>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+< 423 | <]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<< 424 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 425 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>> 426 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 427 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 428 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 429 | <<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 430 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 431 | >>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 432 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 433 | <+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 434 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-] 435 | <<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>> 436 | >>>>>>>>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<] 437 | >>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[- 438 | >>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[-> 439 | +<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 440 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>> 441 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 442 | +<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 443 | <<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 444 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<< 445 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>> 446 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 447 | >>>>>>>>>>>>>+>>>]<]<[->>>>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]>>[-]<< 448 | <<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>>>> 449 | >[-<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>> 450 | >[-]>>>>[-<<<<<<<<+>>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++>>-<]>[[- 451 | ]>[-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>[-]>>>>> 452 | [-<<<<<<<<<<<<<<<<+>>>>>>>>>>>+>>>>>][-]<<<<<<<[->>>>>>>+<<<<<<<]>>>[-]>>>>[ 453 | -<<<<<<<+>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++++++++++++++++++++++ 454 | ++++++++++++++++++++++++++++++++++++>>]<[-]++++++++++++++++>[-]+++++++++++++ 455 | +>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][ 456 | -]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>] 457 | <<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[- 458 | <<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<< 459 | [-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>> 460 | [-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<< 461 | <[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>> 462 | >]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-] 463 | >>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>> 464 | >>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+>>>>>>>>][-]+++++++++++++++++++++++++<<<[ 465 | -]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-][-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<<< 466 | <[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>][-]<<<<<<<< 467 | <<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>]>[-]>[-]< 468 | <<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-]+>>> 469 | [-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<] 470 | <[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[ 471 | -]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[ 472 | [-]<<<<----->>>>][-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<<<<<<+>>>->>>][-]++++++++ 473 | +++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 474 | ++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]>>>[-]>[-]<<<<<[->>> 475 | >>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+> 476 | +>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<< 477 | [-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<] 478 | >>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<< 479 | <]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>> 480 | [-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[ 481 | -]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]< 482 | ]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<< 483 | <+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]< 484 | <<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]< 485 | <[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+ 486 | <<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>> 487 | >>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-< 488 | +>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>> 489 | >>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]> 490 | [-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+ 491 | >>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->> 492 | >+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<< 493 | <<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++ 494 | >[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>> 495 | ]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<] 496 | >>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-] 497 | <[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<< 498 | <<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+ 499 | <<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>> 500 | >[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[- 501 | ]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>] 502 | <[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++++++++++++++++++ 503 | ++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.<++ 504 | ++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<< 505 | <<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++++++++++++++++++ 506 | ++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-<]>[[-]<<<<<<+++ 507 | +++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<<<-------------- 508 | ------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>>>>]>>>[ 509 | -]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[-> 510 | >+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<] 511 | >>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]> 512 | [-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+> 513 | ]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[-> 514 | >>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[- 515 | ]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<< 516 | <+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[- 517 | >>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]< 518 | <<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++ 519 | ++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>> 520 | >>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<< 521 | <]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>> 522 | >[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[ 523 | -]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[- 524 | ]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->> 525 | >+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+ 526 | >>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+> 527 | >]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>> 528 | >>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<] 529 | >>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-] 530 | <<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]< 531 | ]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->> 532 | >]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>> 533 | >>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[- 534 | ]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>> 535 | [[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]> 536 | >[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++ 537 | ++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++ 538 | ++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]> 539 | [-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++ 540 | ++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>- 541 | <]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<< 542 | <<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][ 543 | -]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 544 | ++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>> 545 | >[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->> 546 | >+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+< 547 | ]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++++++++++++++++++++++++++++++++ 548 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 549 | +++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>> 550 | >[-]>>[-<<<<<<<<<<<+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-] 551 | <<<.>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>[-]>>[-<<<<<<<<<<< 552 | +>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[- 553 | >>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++ 554 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<< 555 | [->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[- 556 | ]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<] 557 | [-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[ 558 | -]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 559 | ++++++++++++++++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<< 560 | <<<]>[-]++++++++++.[-]+>[-]+>[-]+++++++++++++++++++++++++++.++++++++++++++++ 561 | ++++++++++++++++++++++++++++++++++++++++++++++++.>[-]>[-]<<<[->>>+<<<]>>>[-< 562 | +<<+>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<< 563 | [>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]< 564 | <<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[ 565 | -<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[ 566 | ->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-] 567 | >[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]< 568 | <[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+ 569 | <<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>> 570 | >>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>] 571 | <[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>> 572 | ][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>> 573 | >>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<< 574 | <<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]< 575 | <<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<< 576 | ->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[ 577 | -]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>> 578 | ]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<] 579 | >>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+ 580 | <<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>> 581 | [-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<< 582 | [->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<< 583 | ->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>] 584 | <<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>> 585 | >]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++ 586 | ++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-< 587 | <<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->> 588 | >>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[- 589 | ]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+> 590 | ]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++ 591 | ++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.> 592 | >>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++ 593 | ++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++ 594 | ++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>> 595 | >>>>]<<]<<<<<<--------------------------------.>[-]>[-]<<<<[->>>>+<<<<]>>>>[ 596 | -<+<<<+>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[ 597 | -]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]> 598 | [-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>> 599 | >>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[ 600 | -]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<< 601 | <[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>> 602 | [-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[- 603 | >>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<< 604 | <+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<< 605 | +>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+> 606 | >>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<< 607 | <]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[ 608 | -]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]< 609 | ]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[- 610 | <<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<< 611 | <<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+ 612 | >>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+< 613 | <<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[ 614 | ->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]> 615 | >>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-] 616 | <<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]< 617 | [<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+ 618 | >>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+ 619 | >>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++ 620 | ++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>> 621 | [[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<< 622 | [->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-] 623 | +>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[ 624 | -<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++ 625 | ++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++ 626 | ++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++ 627 | ++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++ 628 | ++++++++.>>>>>>-<]>[[-]<<<<<<+++++++++++++++++++++++++++++++++++++++++++++++ 629 | +.>>>>>>]<<]<<<<<<+++++++++++++.<<[-]+++++++++++++++++++++++++++++++++++++++ 630 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 631 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 632 | +++++++++[>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 633 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 634 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[>[-]+++++++++ 635 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 636 | +++++++++++++++[-]<-]<-]<<<<<]<<<<+>>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<< 637 | <<+>>>>>][-]++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]> 638 | >>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-> 639 | >>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[-> 640 | +<]>[[-<+>]<<<[-]+>>>]<<<]<<->>[-]<<[->>+<<]>>[[-<<+>>]<<<<<<<<-<<<<<<<<<<<< 641 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 642 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 643 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>> 644 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 645 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 646 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]> 647 | >>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 648 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 649 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>> 650 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 651 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 652 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<< 653 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 654 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 655 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+> 656 | >>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>> 657 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 658 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 659 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 660 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 661 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 662 | <<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>> 663 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 664 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 665 | >>>>>>>>>[-]>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<< 666 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 667 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 668 | <<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 669 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 670 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 671 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 672 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>> 673 | -[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>> 674 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 675 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 676 | >>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 677 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 678 | <<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[- 679 | ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 680 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-]<<<<<<<<<[ 681 | ->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 682 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 683 | <<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 684 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]< 685 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 686 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>> 687 | >>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>> 688 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 689 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<< 690 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 691 | <<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 692 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 693 | [-]>[-]>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>> 694 | >>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]> 695 | [-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-< 696 | <<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<+>]<<<[-]+ 697 | >>>]<<<[<<<<<<<<--------->>+>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>> 698 | >>+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->> 699 | >+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[- 700 | ]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]< 701 | [->+<]>[[-<+>]<<<[-]+>>>]<<<]>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<< 702 | <<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[ 703 | -<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+< 704 | <<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-< 705 | +>]<<<[-]+>>>]<<<[<<<<<<<<--->+>>>>>>>>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>> 706 | +<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+ 707 | <<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]< 708 | <<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[- 709 | >+<]>[[-<+>]<<<[-]+>>>]<<<]<<<<+>>>]<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 710 | -------------------------------------------------------------------------------- /mandel.b: -------------------------------------------------------------------------------- 1 | A mandelbrot set fractal viewer in brainf*** written by Erik Bosman 2 | +++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[ 3 | >>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+ 4 | <<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>> 5 | >+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>> 6 | >>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>> 7 | >>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>> 8 | >>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>> 9 | [>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<< 10 | <<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[ 11 | >>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[ 12 | >+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[ 13 | -<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<< 14 | <<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<< 15 | [>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>> 16 | >>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+ 17 | <<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>> 18 | >>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<< 19 | +>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<< 20 | <]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>> 21 | >>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>> 22 | >>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<< 23 | <<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<< 24 | <<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[-> 25 | >>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<< 26 | <<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++ 27 | +++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>- 28 | <<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>> 29 | [-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<< 30 | <+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[- 31 | ]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<< 32 | <<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]< 33 | <[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>> 34 | >>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>> 35 | [-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-< 36 | <<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>> 37 | ]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+ 38 | >>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[> 39 | [->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[- 40 | ]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>> 41 | [>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 42 | ]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+> 43 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++ 44 | +++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+ 45 | >>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[ 46 | -]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-< 47 | <<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<< 48 | [->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-] 49 | +>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<< 50 | <<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<< 51 | [<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<< 52 | <<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<< 53 | <<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<< 54 | <<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<< 55 | <<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<< 56 | <<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<< 57 | ]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<< 58 | [>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<< 59 | +>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<< 60 | <<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-< 61 | <<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[ 62 | [>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+ 63 | [>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->> 64 | [-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<< 65 | <[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[ 66 | >[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[ 67 | >>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]> 68 | >>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<< 69 | <<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<< 70 | <<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[- 71 | <<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>> 72 | >>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>> 73 | [-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<< 74 | +>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]> 75 | [-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>> 76 | >>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>> 77 | >>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<< 78 | ]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<< 79 | <+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>> 80 | >]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<< 81 | <<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<< 82 | <<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]< 83 | <<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]< 84 | <<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+ 85 | <]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>- 86 | <<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<< 87 | ]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+> 88 | >>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>- 89 | <<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[ 90 | ->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>> 91 | >>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>> 92 | >>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<< 93 | <<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<< 94 | <<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+ 95 | >>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>> 96 | ]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>> 97 | >>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>> 98 | >>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+ 99 | >>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[> 100 | [->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[- 101 | ]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>> 102 | [>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<< 103 | <<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>> 104 | >>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>> 105 | >>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+ 106 | <<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>> 107 | >>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>> 108 | >]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<] 109 | >>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<< 110 | ]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+< 111 | <<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]> 112 | >>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<< 113 | ->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[ 114 | >[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<< 115 | [<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<< 116 | <<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<< 117 | <<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<< 118 | <<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>> 119 | >+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<< 120 | <<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]< 121 | +<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>> 122 | >>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<< 123 | <<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<< 124 | <<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<< 125 | <<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-< 126 | <<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<< 127 | <<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<< 128 | <<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<< 129 | <<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>> 130 | >+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<< 131 | <<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>> 132 | >]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<< 133 | <<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>> 134 | >>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<- 135 | >>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<< 136 | <<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>> 137 | >>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<< 138 | <<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>> 139 | +>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+< 140 | <<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<< 141 | <<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>> 142 | -<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>> 143 | >>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++ 144 | +[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<< 145 | <<<<<]]>>>] 146 | -------------------------------------------------------------------------------- /tutorial.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Writing an Interpreter with PyPy 3 | ================================ 4 | Written by Andrew Brown , with help from the PyPy developers 5 | on the pypy-dev mailing list. 6 | 7 | This tutorial's master copy and supporting files live at 8 | https://bitbucket.org/brownan/pypy-tutorial/ 9 | 10 | When I first learned about the PyPy project, it took me a while to figure out 11 | exactly what it was about. For those that don't already know, it's two things: 12 | 13 | * A set of tools for implementing interpreters for interpreted languages 14 | 15 | * An implementation of Python using this toolchain 16 | 17 | The second part is probably what most people think PyPy is, but this tutorial 18 | is *not* about their Python interpreter. It is about writing your own 19 | interpreter for your own language. 20 | 21 | This is the project I undertook to help myself better understand how PyPy works 22 | and what it's all about. 23 | 24 | This tutorial assumes you know very little about PyPy, how it works, and even 25 | what it's all about. I'm starting from the very beginning here. 26 | 27 | What PyPy Does 28 | ============== 29 | Here's a brief overview of what PyPy can do. Let's say you want to write an 30 | interpreted language. This involves writing some kind of source code parser, a 31 | bytecode interpretation loop, and lots of standard library code. 32 | 33 | That's quite a bit of work for moderately complicated languages, and there's a 34 | lot of low level work involved. Writing the parser and compiler code usually 35 | isn't fun, that's why there are tools out there to generate parsers and 36 | compilers for you. 37 | 38 | Even then, you still must worry about memory management in your interpreter, 39 | and you're going to be re-implementing a lot if you want data types like 40 | arbitrary precision integers, nice general hash tables, and such. It's enough 41 | to put someone off from implementing their idea for a language. 42 | 43 | Wouldn't it be nice if you could write your language in an existing high level 44 | language like, for example, Python? That sure would be ideal, you'd get all the 45 | advantages of a high level language like automatic memory management and rich 46 | data types at your disposal. Oh, but an interpreted language interpreting 47 | another language would be slow, right? That's twice as much interpreting going 48 | on. 49 | 50 | As you may have guessed, PyPy solves this problem. PyPy is a sophisticated 51 | toolchain for analyzing and translating your interpreter code to C code (or JVM 52 | or CLI). This process is called "translation", and it knows how to translate 53 | quite a lot of Python's syntax and standard libraries, but not everything. All 54 | you have to do is write your interpreter in **RPython**, a subset of the Python 55 | language carefully defined to allow this kind of analysis and translation, and 56 | PyPy will produce for you a very efficient interpreter. 57 | 58 | Because efficient interpreters should not be hard to write. 59 | 60 | The Language 61 | ============ 62 | The language I've chosen to implement is dead simple. The language runtime 63 | consists of a tape of integers, all initialized to zero, and a single pointer 64 | to one of the tape's cells. The language has 8 commands, described here: 65 | 66 | > 67 | Moves the tape pointer one cell to the right 68 | 69 | < 70 | Moves the tape pointer one cell to the left 71 | 72 | + 73 | Increments the value of the cell underneath the pointer 74 | 75 | - 76 | Decrements the value of the cell underneath the pointer 77 | 78 | [ 79 | If the cell under the current pointer is 0, skip to the instruction after 80 | the matching ] 81 | 82 | ] 83 | Skip back to the matching [ (evaluating its condition) 84 | 85 | . 86 | Print out a single byte to stdout from the cell under the pointer 87 | 88 | , 89 | Read in a single byte from stdin to the cell under the pointer 90 | 91 | Any unrecognized bytes are ignored. 92 | 93 | Some of you may recognize this language. I will be referring to it as BF. 94 | 95 | One thing to notice is that the language is its own bytecode; there is no 96 | translation from source code to bytecode. This means that the language can be 97 | interpreted directly: the main eval loop of our interpreter will operate right 98 | on the source code. This simplifies the implementation quite a bit. 99 | 100 | First Steps 101 | =========== 102 | Let's start out by writing a BF interpreter in plain old Python. The first step 103 | is sketching out an eval loop:: 104 | 105 | def mainloop(program): 106 | tape = Tape() 107 | pc = 0 108 | while pc < len(program): 109 | code = program[pc] 110 | 111 | if code == ">": 112 | tape.advance() 113 | elif code == "<": 114 | tape.devance() 115 | elif code == "+": 116 | tape.inc() 117 | elif code == "-": 118 | tape.dec() 119 | elif code == ".": 120 | sys.stdout.write(chr(tape.get())) 121 | elif code == ",": 122 | tape.set(ord(sys.stdin.read(1))) 123 | elif code == "[" and value() == 0: 124 | # Skip forward to the matching ] 125 | elif code == "]" and value() != 0: 126 | # Skip back to the matching [ 127 | 128 | pc += 1 129 | 130 | As you can see, a program counter (pc) holds the current instruction index. The 131 | first statement in the loop gets the instruction to execute, and then a 132 | compound if statement decides how to execute that instruction. 133 | 134 | The implementation of [ and ] are left out here, but they should change the 135 | program counter to the value of the matching bracket. (The pc then gets 136 | incremented, so the condition is evaluated once when entering a loop, and once 137 | at the end of each iteration) 138 | 139 | Here's the implementation of the Tape class, which holds the tape's values as 140 | well as the tape pointer:: 141 | 142 | class Tape(object): 143 | def __init__(self): 144 | self.thetape = [0] 145 | self.position = 0 146 | 147 | def get(self): 148 | return self.thetape[self.position] 149 | def set(self, val): 150 | self.thetape[self.position] = val 151 | def inc(self): 152 | self.thetape[self.position] += 1 153 | def dec(self): 154 | self.thetape[self.position] -= 1 155 | def advance(self): 156 | self.position += 1 157 | if len(self.thetape) <= self.position: 158 | self.thetape.append(0) 159 | def devance(self): 160 | self.position -= 1 161 | 162 | As you can see, the tape expands as needed to the right, indefinitely. We 163 | should really add some error checking to make sure the pointer doesn't go 164 | negative, but I'm not worrying about that now. 165 | 166 | Except for the omission of the "[" and "]" implementation, this code will work 167 | fine. However, if the program has a lot of comments, it will have to skip over 168 | them one byte at a time at runtime. So let's parse those out once and for all. 169 | 170 | At the same time, we'll build a dictionary mapping between brackets, so that 171 | finding a matching bracket is just a single dictionary lookup. Here's how:: 172 | 173 | def parse(program): 174 | parsed = [] 175 | bracket_map = {} 176 | leftstack = [] 177 | 178 | pc = 0 179 | for char in program: 180 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 181 | parsed.append(char) 182 | 183 | if char == '[': 184 | leftstack.append(pc) 185 | elif char == ']': 186 | left = leftstack.pop() 187 | right = pc 188 | bracket_map[left] = right 189 | bracket_map[right] = left 190 | pc += 1 191 | 192 | return "".join(parsed), bracket_map 193 | 194 | This returns a string with all invalid instructions removed, and a dictionary 195 | mapping bracket indexes to their matching bracket index. 196 | 197 | All we need is some glue code and we have a working BF interpreter:: 198 | 199 | def run(input): 200 | program, map = parse(input.read()) 201 | mainloop(program, map) 202 | 203 | if __name__ == "__main__": 204 | import sys 205 | run(open(sys.argv[1], 'r')) 206 | 207 | If you're following along at home, you'll also need to change the signature of 208 | mainloop() and implement the bracket branches of the if statement. Here's the 209 | complete example: ``_ 210 | 211 | At this point you can try it out to see that it works by running the 212 | interpreter under python, but be warned, it will be *very* slow on the more 213 | complex examples:: 214 | 215 | $ python example1.py 99bottles.b 216 | 217 | You can find mandel.b and several other example programs (not written by me) in 218 | my repository. 219 | 220 | PyPy Translation 221 | ================ 222 | But this is not about writing a BF interpreter, this is about PyPy. So what 223 | does it take to get PyPy to translate this into a super-fast executable? 224 | 225 | As a side note, there are some simple examples in the pypy/translator/goal 226 | directory of the PyPy source tree that are helpful here. My starting point for 227 | learning this was the example "targetnopstandalone.py", a simple hello world 228 | for PyPy. 229 | 230 | For our example, the module must define a name called "target" which returns the 231 | entry point. The translation process imports your module and looks for that 232 | name, calls it, and the function object returned is where it starts the 233 | translation. 234 | 235 | :: 236 | 237 | def run(fp): 238 | program_contents = "" 239 | while True: 240 | read = os.read(fp, 4096) 241 | if len(read) == 0: 242 | break 243 | program_contents += read 244 | os.close(fp) 245 | program, bm = parse(program_contents) 246 | mainloop(program, bm) 247 | 248 | def entry_point(argv): 249 | try: 250 | filename = argv[1] 251 | except IndexError: 252 | print "You must supply a filename" 253 | return 1 254 | 255 | run(os.open(filename, os.O_RDONLY, 0777)) 256 | return 0 257 | 258 | def target(*args): 259 | return entry_point, None 260 | 261 | if __name__ == "__main__": 262 | entry_point(sys.argv) 263 | 264 | The entry_point function is passed the command line arguments when you run the 265 | resulting executable. 266 | 267 | A few other things have changed here too. See the next section... 268 | 269 | About RPython 270 | ============= 271 | Let's talk a bit about RPython at this point. PyPy can't translate arbitrary 272 | Python code because Python is a bit too dynamic. There are restrictions on what 273 | standard library functions and what syntax constructs one can use. I won't be 274 | going over all the restrictions, but for more information see 275 | http://readthedocs.org/docs/pypy/en/latest/coding-guide.html#restricted-python 276 | 277 | In the example above, you'll see a few things have changed. I'm now using low 278 | level file descriptors with os.open and os.read instead of file objects. 279 | The implementation of "." and "," are similarly tweaked (not shown above). 280 | Those are the only changes to make to this code, the rest is simple enough for 281 | PyPy to digest. 282 | 283 | That wasn't so hard, was it? I still get to use dictionaries, expandable lists, 284 | and even classes and objects! And if low level file descriptors are too low for 285 | you, there are some helpful abstractions in the rlib.streamio module included 286 | with PyPy's "RPython standard library." 287 | 288 | For the example thus far, see ``_ 289 | 290 | Translating 291 | =========== 292 | If you haven't already, check yourself out the latest version of PyPy from 293 | their bitbucket.org repository:: 294 | 295 | $ hg clone https://bitbucket.org/pypy/pypy 296 | 297 | (A recent revision is necessary because of a bugfix that makes my example 298 | possible) 299 | 300 | The script to run is in "pypy/translator/goal/translate.py". Run this script, 301 | passing in our example module as an argument. 302 | 303 | :: 304 | 305 | $ python ./pypy/rpython/bin/rpython example2.py 306 | 307 | (You can use PyPy's python interpreter for extra speed, but it's not necessary) 308 | 309 | PyPy will churn for a bit, drawing some nice looking fractals to your console 310 | while it works. It takes around 20 seconds on my machine. 311 | 312 | The result from this is an executable binary that interprets BF programs. 313 | Included in my repository are some example BF programs, including a mandelbrot 314 | fractal generator, which takes about 45 seconds to run on my computer. Try it 315 | out:: 316 | 317 | $ ./example2-c mandel.b 318 | 319 | Compare this to running the interpreter un-translated on top of python:: 320 | 321 | $ python example2.py mandel.b 322 | 323 | Takes forever, doesn't it? 324 | 325 | So there you have it. We've successfully written our own interpreter in RPython 326 | and translated it with the PyPy toolchain. 327 | 328 | Adding JIT 329 | ========== 330 | Translating RPython to C is pretty cool, but one of the best features of PyPy 331 | is its ability to *generate just-in-time compilers for your interpreter*. 332 | That's right, from just a couple hints on how your interpreter is structured, 333 | PyPy will generate and include a JIT compiler that will, at runtime, translate 334 | the interpreted code of our BF language to machine code! 335 | 336 | So what do we need to tell PyPy to make this happen? First it needs to know 337 | where the start of your bytecode evaluation loop is. This lets it keep track of 338 | instructions being executed in the target language (BF). 339 | 340 | We also need to let it know what defines a particular execution frame. Since 341 | our language doesn't really have stack frames, this boils down to what's 342 | constant for the execution of a particular instruction, and what's not. These 343 | are called "green" and "red" variables, respectively. 344 | 345 | Refer back to ``_ for the following. 346 | 347 | In our main loop, there are four variables used: pc, program, bracket_map, and 348 | tape. Of those, pc, program, and bracket_map are all green variables. They 349 | *define* the execution of a particular instruction. If the JIT routines see the 350 | same combination of green variables as before, it knows it's skipped back and 351 | must be executing a loop. The variable "tape" is our red variable, it's what's 352 | being manipulated by the execution. 353 | 354 | So let's tell PyPy this info. Start by importing the JitDriver class and making 355 | an instance:: 356 | 357 | from rpython.rlib.jit import JitDriver 358 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], 359 | reds=['tape']) 360 | 361 | And we add this line to the very top of the while loop in the mainloop 362 | function:: 363 | 364 | jitdriver.jit_merge_point(pc=pc, tape=tape, program=program, 365 | bracket_map=bracket_map) 366 | 367 | We also need to define a JitPolicy. We're not doing anything fancy, so this is 368 | all we need somewhere in the file:: 369 | 370 | def jitpolicy(driver): 371 | from rpython.jit.codewriter.policy import JitPolicy 372 | return JitPolicy() 373 | 374 | See this example at ``_ 375 | 376 | Now try translating again, but with the flag ``--opt=jit``:: 377 | 378 | $ python ./pypy/rpython/bin/rpython --opt=jit example3.py 379 | 380 | It will take significantly longer to translate with JIT enabled, almost 8 381 | minutes on my machine, and the resulting binary will be much larger. When it's 382 | done, try having it run the mandelbrot program again. A world of difference, 383 | from 12 seconds compared to 45 seconds before! 384 | 385 | Interestingly enough, you can see when the JIT compiler switches from 386 | interpreted to machine code with the mandelbrot example. The first few lines of 387 | output come out pretty fast, and then the program gets a boost of speed and 388 | gets even faster. 389 | 390 | A bit about Tracing JIT Compilers 391 | ================================= 392 | It's worth it at this point to read up on how tracing JIT compilers work. 393 | Here's a brief explanation: The interpreter is usually running your interpreter 394 | code as written. When it detects a loop of code in the target language (BF) is 395 | executed often, that loop is considered "hot" and marked to be traced. The next 396 | time that loop is entered, the interpreter gets put in tracing mode where every 397 | executed instruction is logged. 398 | 399 | When the loop is finished, tracing stops. The trace of the loop is sent to an 400 | optimizer, and then to an assembler which outputs machine code. That machine 401 | code is then used for subsequent loop iterations. 402 | 403 | This machine code is often optimized for the most common case, and depends on 404 | several assumptions about the code. Therefore, the machine code will contain 405 | guards, to validate those assumptions. If a guard check fails, the runtime 406 | falls back to regular interpreted mode. 407 | 408 | A good place to start for more information is 409 | http://en.wikipedia.org/wiki/Just-in-time_compilation 410 | 411 | Debugging and Trace Logs 412 | ======================== 413 | Can we do any better? How can we see what the JIT is doing? Let's do two 414 | things. 415 | 416 | First, let's add a get_printable_location function, which is used during debug 417 | trace logging:: 418 | 419 | def get_location(pc, program, bracket_map): 420 | return "%s_%s_%s" % ( 421 | program[:pc], program[pc], program[pc+1:] 422 | ) 423 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], reds=['tape'], 424 | get_printable_location=get_location) 425 | 426 | This function is passed in the green variables, and should return a string. 427 | Here, we're printing out the BF code, surrounding the currently executing 428 | instruction with underscores so we can see where it is. 429 | 430 | Download this as ``_ and translate it the same as example3.py. 431 | 432 | Now let's run a test program (test.b, which just prints the letter "A" 15 or so 433 | times in a loop) with trace logging:: 434 | 435 | $ PYPYLOG=jit-log-opt:logfile ./example4-c test.b 436 | 437 | Now take a look at the file "logfile". This file is quite hard to read, so 438 | here's my best shot at explaining it. 439 | 440 | The file contains a log of every trace that was performed, and is essentially a 441 | glimpse at what instructions it's compiling to machine code for you. It's 442 | useful to see if there are unnecessary instructions or room for optimization. 443 | 444 | Each trace starts with a line that looks like this:: 445 | 446 | [3c091099e7a4a7] {jit-log-opt-loop 447 | 448 | and ends with a line like this:: 449 | 450 | [3c091099eae17d jit-log-opt-loop} 451 | 452 | The next line tells you which loop number it is, and how many ops are in it. 453 | In my case, the first trace looks like this:: 454 | 455 | 456 | 1 [3c167c92b9118f] {jit-log-opt-loop 457 | 2 # Loop 0 : loop with 26 ops 458 | 3 [p0, p1, i2, i3] 459 | 4 debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 460 | 5 debug_merge_point('+<[>[>_+_<-]>.[<+>-]<<-]++++++++++.', 0) 461 | 6 i4 = getarrayitem_gc(p1, i2, descr=) 462 | 7 i6 = int_add(i4, 1) 463 | 8 setarrayitem_gc(p1, i2, i6, descr=) 464 | 9 debug_merge_point('+<[>[>+_<_-]>.[<+>-]<<-]++++++++++.', 0) 465 | 10 debug_merge_point('+<[>[>+<_-_]>.[<+>-]<<-]++++++++++.', 0) 466 | 11 i7 = getarrayitem_gc(p1, i3, descr=) 467 | 12 i9 = int_sub(i7, 1) 468 | 13 setarrayitem_gc(p1, i3, i9, descr=) 469 | 14 debug_merge_point('+<[>[>+<-_]_>.[<+>-]<<-]++++++++++.', 0) 470 | 15 i10 = int_is_true(i9) 471 | 16 guard_true(i10, descr=) [p0] 472 | 17 i14 = call(ConstClass(ll_dict_lookup__dicttablePtr_Signed_Signed), ConstPtr(ptr12), 90, 90, descr=) 473 | 18 guard_no_exception(, descr=) [i14, p0] 474 | 19 i16 = int_and(i14, -9223372036854775808) 475 | 20 i17 = int_is_true(i16) 476 | 21 guard_false(i17, descr=) [i14, p0] 477 | 22 i19 = call(ConstClass(ll_get_value__dicttablePtr_Signed), ConstPtr(ptr12), i14, descr=) 478 | 23 guard_no_exception(, descr=) [i19, p0] 479 | 24 i21 = int_add(i19, 1) 480 | 25 i23 = int_lt(i21, 114) 481 | 26 guard_true(i23, descr=) [i21, p0] 482 | 27 guard_value(i21, 86, descr=) [i21, p0] 483 | 28 debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 484 | 29 jump(p0, p1, i2, i3, descr=) 485 | 30 [3c167c92bc6a15] jit-log-opt-loop} 486 | 487 | I've trimmed the debug_merge_point lines a bit, they were really long. 488 | 489 | So let's see what this does. This trace takes 4 parameters: 2 object pointers 490 | (p0 and p1) and 2 integers (i2 and i3). Looking at the debug lines, it seems to 491 | be tracing one iteration of this loop: "[>+<-]" 492 | 493 | It starts executing the first operation on line 4, a ">", but immediately 494 | starts executing the next operation. The ">" had no instructions, and looks 495 | like it was optimized out completely. This loop must always act on the same 496 | part of the tape, the tape pointer is constant for this trace. An explicit 497 | advance operation is unnecessary. 498 | 499 | Lines 5 to 8 are the instructions for the "+" operation. First it gets the 500 | array item from the array in pointer p1 at index i2 (line 6), adds 1 to it and 501 | stores it in i6 (line 7), and stores it back in the array (line 8). 502 | 503 | Line 9 starts the "<" instruction, but it is another no-op. It seems that i2 504 | and i3 passed into this routine are the two tape pointers used in this loop 505 | already calculated. Also deduced is that p1 is the tape array. It's not clear 506 | what p0 is. 507 | 508 | Lines 10 through 13 perform the "-" operation: get the array value (line 11), 509 | subtract (line 12) and set the array value (line 13). 510 | 511 | Next, on line 14, we come to the "]" operation. Lines 15 and 16 check whether 512 | i9 is true (non-zero). Looking up, i9 is the array value that we just 513 | decremented and stored, now being checked as the loop condition, as expected 514 | (remember the definition of "]"). Line 16 is a guard, if the condition is not 515 | met, execution jumps somewhere else, in this case to the routine called 516 | and is passed one parameter: p0. 517 | 518 | Assuming we pass the guard, lines 17 through 23 are doing the dictionary lookup 519 | to bracket_map to find where the program counter should jump to. I'm not too 520 | familiar with what the instructions are actually doing, but it looks like there 521 | are two external calls and 3 guards. This seems quite expensive, especially 522 | since we know bracket_map will never change (PyPy doesn't know that). We'll 523 | see below how to optimize this. 524 | 525 | Line 24 increments the newly acquired instruction pointer. Lines 25 and 26 make 526 | sure it's less than the program's length. 527 | 528 | Additionally, line 27 guards that i21, the incremented instruction pointer, is 529 | exactly 86. This is because it's about to jump to the beginning (line 29) and 530 | the instruction pointer being 86 is a precondition to this block. 531 | 532 | Finally, the loop closes up at line 28 so the JIT can jump to loop body 533 | to handle that case (line 29), which is the beginning of the loop again. It 534 | passes in parameters (p0, p1, i2, i3). 535 | 536 | Optimizing 537 | ========== 538 | As mentioned, every loop iteration does a dictionary lookup to find the 539 | corresponding matching bracket for the final jump. This is terribly 540 | inefficient, the jump target is not going to change from one loop to the next. 541 | This information is constant and should be compiled in as such. 542 | 543 | The problem is that the lookups are coming from a dictionary, and PyPy is 544 | treating it as opaque. It doesn't know the dictionary isn't being modified or 545 | isn't going to return something different on each query. 546 | 547 | What we need to do is provide another hint to the translation to say that the 548 | dictionary query is a pure function, that is, its output depends *only* on its 549 | inputs and the same inputs should always return the same output. 550 | 551 | To do this, we use a provided function decorator rpython.rlib.jit.purefunction, 552 | and wrap the dictionary call in a decorated function:: 553 | 554 | @purefunction 555 | def get_matching_bracket(bracket_map, pc): 556 | return bracket_map[pc] 557 | 558 | This version can be found at ``_ 559 | 560 | Translate again with the JIT option and observe the speedup. Mandelbrot now 561 | only takes 6 seconds! (from 12 seconds before this optimization) 562 | 563 | Let's take a look at the trace from the same function:: 564 | 565 | [3c29fad7b792b0] {jit-log-opt-loop 566 | # Loop 0 : loop with 15 ops 567 | [p0, p1, i2, i3] 568 | debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 569 | debug_merge_point('+<[>[>_+_<-]>.[<+>-]<<-]++++++++++.', 0) 570 | i4 = getarrayitem_gc(p1, i2, descr=) 571 | i6 = int_add(i4, 1) 572 | setarrayitem_gc(p1, i2, i6, descr=) 573 | debug_merge_point('+<[>[>+_<_-]>.[<+>-]<<-]++++++++++.', 0) 574 | debug_merge_point('+<[>[>+<_-_]>.[<+>-]<<-]++++++++++.', 0) 575 | i7 = getarrayitem_gc(p1, i3, descr=) 576 | i9 = int_sub(i7, 1) 577 | setarrayitem_gc(p1, i3, i9, descr=) 578 | debug_merge_point('+<[>[>+<-_]_>.[<+>-]<<-]++++++++++.', 0) 579 | i10 = int_is_true(i9) 580 | guard_true(i10, descr=) [p0] 581 | debug_merge_point('+<[>[_>_+<-]>.[<+>-]<<-]++++++++++.', 0) 582 | jump(p0, p1, i2, i3, descr=) 583 | [3c29fad7ba32ec] jit-log-opt-loop} 584 | 585 | Much better! Each loop iteration is an add, a subtract, two array loads, two 586 | array stores, and a guard on the exit condition. That's it! This code doesn't 587 | require *any* program counter manipulation. 588 | 589 | I'm no expert on optimizations, this tip was suggested by Armin Rigo on the 590 | pypy-dev list. Carl Friedrich has a series of posts on how to optimize your 591 | interpreter that are also very useful: http://bit.ly/bundles/cfbolz/1 592 | 593 | Final Words 594 | =========== 595 | I hope this has shown some of you what PyPy is all about other than a faster 596 | implementation of Python. 597 | 598 | For those that would like to know more about how the process works, there are 599 | several academic papers explaining the process in detail that I recommend. In 600 | particular: Tracing the Meta-Level: PyPy's Tracing JIT Compiler. 601 | 602 | See http://readthedocs.org/docs/pypy/en/latest/extradoc.html 603 | --------------------------------------------------------------------------------