PageRenderTime 25ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/by_others/cgbfi2.bf

https://github.com/ryantenney/brainfuck
Brainfuck | 401 lines | 344 code | 57 blank | 0 comment | 435 complexity | d1fe788eb97393304b653432537f2622 MD5 | raw file
  1. Brainfuck Self Interpreter: by Clive Gifford
  2. http://homepages (dot) xnet (dot) co (dot) nz/~clive/eigenratios/cgbfi2 (dot) b
  3. Version 1: 01 December 2006 (one trip between code and data per op)
  4. Version 2: 16 December 2006 (virtual codes for various combinations)
  5. Credits
  6. A large section of code to load the input to the interpreter is copied
  7. from the the 423 byte dbfi interpreter as described in the November 2003
  8. paper "A Very Small Interpeter" by Oleg Mazonka and Daniel B Cristofani
  9. Goals
  10. The goal for this interpreter was to be efficient rather than small and
  11. particularly to allow as many copies of itself as possible to be "stacked"
  12. up with something else on top / In other words to achieve a low "eigenratio"
  13. (See http eigenratios dot blogspot dot com for more information)
  14. The main idea of the first version was to only make one round trip between
  15. the emulated code and emulated data for each instruction executed instead
  16. of multiple round trips which is what Daniel and Oleg's version does
  17. The second version does more pre processing of the guest program in order
  18. to map several common sequences to virtual codes thus reducing the memory
  19. footprint and also further reducing the number of round trips between the
  20. emulated code and data
  21. Other info:
  22. The input must consist of valid brainfuck code (to be interpreted) which
  23. must always be followed by an exclamation mark and then any associated data
  24. Input can also include "comments" (if desired) except for exclamation mark
  25. If you are stacking multiple copies of this interpreter then each additional
  26. level also has to appear in the input with a trailing exclamation mark and
  27. then we finally have the input for the very top level to finish things off
  28. The underlying brainfuck machine determines the possible range of values in
  29. the data cell values and what happens if an attempt is made to go outside the
  30. supported range but this interpreter does not more than 8 bit data itself
  31. Loops in the emulated code can be nested up to the maximum cell value in the
  32. underlying machine and this interpreter requires that at least 17 levels of
  33. nesting is supported
  34. Behaviour on end of input is also inherited from the next level down
  35. >>>> leave a little extra space before the program code
  36. + start in left hand cell of first program code pair
  37. [
  38. ->>> clear flag and move to the starting position
  39. ++>+>+++++++ setup differences and read char as per dbfi
  40. [<++++>>++<-]++>>+>+> (by Daniel B Cristofani)
  41. +++++[>++>++++++<<-]
  42. +>>>,<++
  43. [
  44. [>[->>]<[>>]<<-] see section 3 of dbfi paper
  45. <[<]<+>>[>]>
  46. [ see section 4 of dbfi paper
  47. <+>-
  48. [[<+>-]>] see section 5 of dbfi paper
  49. < see section 6 of dbfi paper
  50. [
  51. [[-]<] scan left and zero the differences
  52. ++<- see section 7 of dbfi paper
  53. [
  54. <+++++++++>[<->-]>>
  55. ]
  56. >>
  57. ]
  58. ]
  59. <<
  60. ]
  61. a three way switch to handle possibilities and adjust positioning
  62. >[-]+<< set "done" flag and position to value
  63. [
  64. -- 2 means last decode was for a valid instruction
  65. [ so if we still have something left now it was a 9
  66. [-] originally (meaning input should be ignored)
  67. >>- <<<+> so all we do is set the "more input" flag
  68. ]
  69. >>
  70. [
  71. -
  72. <<<<[>+<-] for valid input move everything right one
  73. start of processing to find and recode certain combinations of codes
  74. +<<+ set flags to indicate we want to process
  75. the last two instructions in the loop below
  76. [
  77. -> clear flag and move to instruction
  78. [<+>>>>>>+<<<<<-] double copy instruction and then
  79. <[>+<-]>>>>>> restore original before moving to copy
  80. map relevant codes to values giving unique pairwise sums and also
  81. set a flag if we see the end of a loop
  82. >+<
  83. [
  84. -[
  85. -[
  86. -[
  87. -[
  88. -[
  89. -[
  90. -[
  91. -[
  92. [-]
  93. >-<
  94. ]>[-<<+++++++>>] <
  95. ]
  96. ]
  97. ]>[-]<
  98. ]>[-<<+++>>]<
  99. ]>[-<<+>>]<
  100. ]>[-]<
  101. ]>[-<<<<<<<+>>>>>>>]< set flag if it is end of loop
  102. ]>[-]<
  103. <<<< goto next instruction flag
  104. ]
  105. add values from above together to get unique sum
  106. >>>[<<+>>-]
  107. <+<
  108. setup a switch to figure out what it means
  109. [
  110. -[
  111. -[
  112. -[
  113. -[
  114. -[
  115. -[
  116. -[
  117. -[
  118. -[
  119. -[
  120. [-]
  121. >-<<<[-]<<+>> change code 8 (add 1) to 9 (add 2)
  122. ]
  123. ]
  124. ]
  125. ]>[-]<
  126. ]>[-<<<[-]<<+++++++>>>]< change code 4 (left) to 11 (left 2)
  127. ]
  128. ]
  129. ]>[-]<
  130. ]>[-<<<[-]<<+++++++>>>]< change code 3 (right) to 10 (right 2)
  131. ]
  132. ]>[-]<
  133. clear flag set if second to last was end of loop
  134. and go to similar flag for last instruction
  135. <<<<<[-]>>
  136. [
  137. -
  138. <<<[>+>>+<<<-]>[<+>-]>> copy third to last instruction
  139. if it is the start of a loop then we can (in some cases)
  140. collapse the last three instructions to single virtual code
  141. [
  142. -[
  143. -[
  144. [-]
  145. >>
  146. ]
  147. >
  148. [ Now we are ready to check what code is in the loop (must be at least 1)
  149. <<[<+>>+<-]>[<+>-]+<<
  150. -
  151. [
  152. -[
  153. -[
  154. -[
  155. -[
  156. -[
  157. -[
  158. -[
  159. -[
  160. -[
  161. -
  162. <+> fall through & code as 16 (double skip left)
  163. ]<+++++++++++++>>[-]>->-<< code as 15 (double skip right)
  164. ]
  165. ]
  166. ]>>[->>>>>]<<
  167. ]>>[-<<<++++++++++++>>[-]>>-]<< code as 14 (zero)
  168. ]>>[->>>>>]<<
  169. ]>>[-<<<+++++++++++>>[-]>>-]<< code as 13 (skip left)
  170. ]>>[-<<<++++++++++>>[-]>>-]<< code as 12 (skip right)
  171. ]
  172. ]>>[->>>>>]<<
  173. ]
  174. <
  175. ]
  176. ]>[>>]<
  177. <<
  178. ]
  179. >>+>>>
  180. ]
  181. <<
  182. ]
  183. >> [->+>] << end of input so clear "done" and set data mark and
  184. finally position to a zero cell ready for next phase
  185. < move to "more input" flag
  186. ]
  187. <<[<<]>> go to the first instruction
  188. ******** MAIN INTERPRETER LOOPS STARTS HERE ********
  189. [ start on current instruction code
  190. setup a big switch statement to decode instructions
  191. [<+>>+<-] move/copy instruction code and set "done" flag to
  192. +<- start with '(i less 1) (1) (i) for i = instruction
  193. [
  194. -[
  195. -[
  196. -[
  197. -[
  198. -[
  199. -[
  200. -[
  201. -[
  202. -[
  203. -[
  204. -[
  205. -[
  206. -[
  207. -[
  208. - can't be anything but 1 so bracketing not needed
  209. >->> [>>] >> [>>]< [<-<<-<] <[<<] << [<<]< double skip left (code 16)
  210. ]
  211. >[->> [>>] >> [>>]< [>+>>+>] <[<<] << [<<]]< double skip right (code 15)
  212. ]
  213. >[->> [>>] >> [>>] <[-]< [<<] << [<<]]< zero (code 14)
  214. ]
  215. >[->> [>>] >> [>>]< [<-<] <[<<] << [<<]]< skip left (code 13)
  216. ]
  217. >[->> [>>] >> [>>]< [>+>] <[<<] << [<<]]< skip right (code 12)
  218. ]
  219. >[->> [>>] >> [>>]< <-<<-< <[<<] << [<<]]< double move left (code 11)
  220. ]
  221. >[->> [>>] >> [>>] +>>+ [<<] << [<<]]< double move right (code 10)
  222. ]
  223. >[->> [>>] >> [>>]< ++ <[<<] << [<<]]< add 2 (code 9)
  224. ]
  225. >[->> [>>] >> [>>]< + <[<<] << [<<]]< increment
  226. ]
  227. >[->> [>>] >> [>>]< , <[<<] << [<<]]< input
  228. ]
  229. >[->> [>>] >> [>>]< - <[<<] << [<<]]< decrement
  230. ]
  231. >[->> [>>] >> [>>]< . <[<<] << [<<]]< output
  232. ]
  233. >[->> [>>] >> [>>] <<-<< [<<] << [<<]]< move left
  234. ]
  235. >[->> [>>] >> [>>] + [<<] << [<<]]< move right
  236. ]
  237. >
  238. [- left hand bracket
  239. >> [>>] >> [>>]< move to data cell
  240. [>+>>+<<<-]> make double copy and move to first
  241. [<+>-] restore original data cell value
  242. >>[<<+>>[-]]+ This and the following achieves
  243. <<[>>-<<-] x = not x
  244. >> go to flag cell (0 or 1)
  245. Some tricky stuff here: set up (not flag) also so we can later choose
  246. appropriate instruction sequence to get back to code area in one pass
  247. In one case we set flags at the other end (data greater than 0) but
  248. for the other we just go back without setting any flags (data equals 0)
  249. [<<+>>>>+<<-] make two copies of flag
  250. >>[<<+>>-]
  251. <<[>>+<<-]+ This and the following achieves
  252. >>[<<->>-]<< x = not x
  253. << so we now have (data) '(flag) (?) (not flag)
  254. [ if flag set then
  255. -<< [<<] << [<<]< clear and return to code section where we save
  256. << << ++ a 2 meaning we need (later) to match left bracket
  257. >> stop in zero cell for now
  258. ]
  259. >> if we executed code above then now at switch flag
  260. else it will put us ready to return from data area
  261. [-<<<<<<[<<]<<[<<]<] move back to switch flag without setting anything
  262. >
  263. ]
  264. <
  265. ]
  266. >
  267. [- right hand bracket
  268. >> [>>] >> [>>]< move to data cell
  269. [>+>>+<<<-]> make double copy and move to first
  270. [[<+>-]>>[-]+<<] restore data from one then zero second and set flag
  271. >> go to flag cell (0 or 1)
  272. Some tricky stuff here: set up (not flag) also so we can later choose
  273. appropriate instruction sequence to get back to code area in one pass
  274. In one case we set flags at the other end (data greater than 0) but
  275. for the other we just go back without setting any flags (data equals 0)
  276. [<<+>>>>+<<-] make two copes of flag
  277. >>[<<+>>-]
  278. <<[>>+<<-]+ This and the following achieves
  279. >>[<<->>-]<< x = not x
  280. << so we now have (data) '(flag) (?) (not flag)
  281. [ if flag set then
  282. -<< [<<] << [<<]< clear and return to code section where we save
  283. << << + a 1 meaning we need (later) to match right bracket
  284. >> stop in zero cell for now
  285. ]
  286. >> if we executed code above then now at switch flag
  287. else it will put us ready to return from data area
  288. [-<<<<<<[<<]<<[<<]<] move back to switch flag without setting anything
  289. >
  290. ]
  291. >[<+>-] restore original instruction code
  292. *** We are positioned in the cell immediately to the right of the ***
  293. *** instruction that has just been "executed" in the switch above ***
  294. *** The following code is to handle finding matching brackets ***
  295. *** because code above has only set a cell value to 1 or 2 to show ***
  296. *** what kind of loop scanning is required (1=scan left 2=right) ***
  297. << << << position to cell showing if matching required
  298. [ if non zero we need to find a matching bracket
  299. >> + set up "done" flag for switch and
  300. << - decrement switch value so now is 0 or 1
  301. [ if 1 we are looking for matching right bracket
  302. - >> - >> + clear switch value & "done" & set level to 1
  303. [ while level is more than 0
  304. >>>[-<+>>+<] make double copy of instruction code
  305. +<- set flag and prepare for switch
  306. [
  307. -[
  308. [-] clear whatever is left of code
  309. > - < do nothing except clear flag
  310. ]
  311. > [- <<< + >>>] < increment level
  312. ]
  313. > [- <<< - >>>] decrement level
  314. >[-<+>]<< restore instruction code
  315. << go to level
  316. [>>+<<-] if level then move right one instruction
  317. >>
  318. ]
  319. << << << go back to switch value cell
  320. ]
  321. >> go to switch done flag and if still set then
  322. [ we must be looking for a matching left bracket
  323. - << + clear switch value & "done" & set level to 1
  324. [ repeat while level is more than 0
  325. >>>[-<+>>+<] make double copy of instruction code
  326. +<- set flag and prepare for switch
  327. [
  328. -[
  329. [-] clear whatever is left of code
  330. > - < do nothing except clear flag
  331. ]
  332. > [- <<< - >>>] < decrement level
  333. ]
  334. > [- <<< + >>>] increment level
  335. >[-<+>]<< restore instruction code
  336. << go to level
  337. [<<+>>-] if level then move left one instruction
  338. <<
  339. ]
  340. ]
  341. ]
  342. >> >> >>
  343. > move forward to next instruction
  344. ]