/self-interpreters/by-clive-gifford.bf

https://github.com/cagataycali/awesome-brainfuck · Brainfuck · 399 lines · 343 code · 56 blank · 0 comment · 435 complexity · f2df20312e8384196936b40570abe951 MD5 · raw file

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