Advertisement
B1KMusic

brainfuck implementation details

Jun 27th, 2020
268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.32 KB | None | 0 0
  1. in reply to: https://www.youtube.com/watch?v=qK0vmuQib8Y
  2. regarding: overcomplicated [ ] jump logic
  3.  
  4. // +
  5. ++*ptr;
  6.  
  7. // -
  8. --*ptr;
  9.  
  10. // <
  11. --ptr;
  12.  
  13. // >
  14. ++ptr;
  15.  
  16. // ,
  17. *ptr = getchar();
  18.  
  19. // .
  20. putchar(*ptr);
  21.  
  22. // [
  23. if(*ptr == 0)
  24. pc = bracket_seek(pc, pc + strlen(pc), '[', ']');
  25.  
  26. // ]
  27. pc = bracket_seek_r(pc, code, ']', '[') - 1;
  28.  
  29. // description of functions and variables
  30. char *ptr
  31. pointer to working memory
  32.  
  33. char *pc
  34. pointer to current instruction (program counter)
  35.  
  36. char *code
  37. pointer to beginning of instruction pool
  38.  
  39. char *bracket_seek(char *start, char *end, char bracket, char match)
  40. assume program has been sanitized and stripped of non-instruction characters
  41. returns a position within the array pointed to by start.
  42. Undefined behavior will occur if misused.
  43. start is where the seek will begin
  44. end must be greater than start, seek must return NULL (representing end of program)
  45. if no match is found before start overtakes end
  46. bracket is the character being seeked from. If bracket is found before match, a counter is incremented
  47. match is the character for the matching bracket. If counter > 0 when match is found,
  48. decrement counter and continue. Else, return the current seek position
  49.  
  50. char *bracket_seek_r(char *start, char *end, char bracket, char match)
  51. same as bracket_seek, except it seeks in reverse, and thus end must be
  52. less than start or undefined behavior will occur
  53.  
  54. // sample implementation (untested):
  55.  
  56. char *
  57. bracket_seek(char *start, char *end, char bracket, char match)
  58. {
  59. int depth = 0;
  60.  
  61. while(++start < end){
  62. if(*start == bracket)
  63. ++depth;
  64.  
  65. if(*start == match){
  66. if(depth > 0){
  67. --depth;
  68. continue;
  69. }
  70.  
  71. return start;
  72. }
  73. }
  74.  
  75. return NULL;
  76. }
  77.  
  78. char *
  79. bracket_seek_r(char *start, char *end, char bracket, char match)
  80. {
  81. int depth = 0;
  82.  
  83. while(--start >= end){
  84. if(*start == bracket)
  85. ++depth;
  86.  
  87. if(*start == match){
  88. if(depth > 0){
  89. --depth;
  90. continue;
  91. }
  92.  
  93. return start;
  94. }
  95. }
  96.  
  97. return NULL;
  98. }
  99.  
  100. // note: it would be a good idea to find a way to avoid duplicate code, e.g. by making a bracket_seek_generic function that takes a seek direction as an additional argument, and is wrapped by the two single-purpose functions (bracket_seek and bracket_seek_r), so as to minimize both excessive arguments and code duplication.
  101.  
  102. char *
  103. bracket_seek_generic(char *start, char *end, char bracket, char match, int direction)
  104. {
  105. int depth = 0;
  106.  
  107. if(direction == 0)
  108. return NULL;
  109.  
  110. while( (direction > 0 && ++start < end) ||
  111. (direction < 0 && --start >= end) ){
  112.  
  113. if(*start == bracket)
  114. ++depth;
  115.  
  116. if(*start == match){
  117. if(depth > 0){
  118. --depth;
  119. continue;
  120. }
  121.  
  122. return start;
  123. }
  124. }
  125.  
  126. return NULL;
  127. }
  128.  
  129. char *
  130. bracket_seek(char *start, char *end, char bracket, char match)
  131. {
  132. return bracket_seek_generic(start, end, bracket, match, +1);
  133. }
  134.  
  135. char *
  136. bracket_seek_r(char *start, char *end, char bracket, char match)
  137. {
  138. return bracket_seek_generic(start, end, bracket, match, -1);
  139. }
  140.  
  141. // doing this, the two bracket_seek functions act as wrappers to a bigger function. This saves on duplicate code in the sense that the implementations of bracket_seek and bracket_seek_r are obviously correct and won't need to be updated in parallel (debugging will happen entirely in bracket_seek_generic), and also avoids the problem of having too many arguments, as the functions that are meant to be used by downstream code have a much simpler interface. However, the drawback is that bracket_seek_generic has more complexity and is thus more bug-prone. Choose your battles.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement