repos / gbc

GBC - Go B Compiler
git clone https://github.com/xplshn/gbc.git

gbc / examples
xplshn  ·  2025-08-13

brainfck.b

B
  1// Copyright (c) 2025 luxluth <[email protected]>
  2//
  3// Permission is hereby granted, free of charge, to any person obtaining a copy
  4// of this software and associated documentation files (the "Software"), to deal
  5// in the Software without restriction, including without limitation the rights
  6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7// copies of the Software, and to permit persons to whom the Software is
  8// furnished to do so, subject to the following conditions:
  9//
 10// The above copyright notice and this permission notice shall be included in all
 11// copies or substantial portions of the Software.
 12//
 13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 19// SOFTWARE.
 20
 21
 22STDIN;
 23BUF_LEN;
 24MEMORY_LEN;
 25
 26main() {
 27  extrn malloc, memset, read, printf, getchar, atoi, fflush;
 28  auto memory, cursor, len, input_buf, stop, addr_buf, W;
 29
 30  MEMORY_LEN = 30000; STDIN = 0; BUF_LEN = 512;
 31
 32  W      = &0[1];
 33  cursor = 0;
 34  stop   = 0;
 35
 36  memory    = malloc(MEMORY_LEN*W);
 37  addr_buf  = malloc(5);
 38  input_buf = malloc(BUF_LEN);
 39
 40  memset(memory, 0, MEMORY_LEN*W);
 41  memset(addr_buf, 0, 5);
 42  memset(input_buf, 0, BUF_LEN);
 43
 44  while (!stop) {
 45    auto cmdslen; cmdslen = 0;
 46    auto input_cursor; input_cursor = 0;
 47
 48    printf("# ");
 49    fflush(0);
 50    cmdslen = read(STDIN, input_buf, BUF_LEN);
 51    if (cmdslen > 0) {
 52      *(input_buf + cmdslen - 1) = 0; // removing the extra newline
 53      cmdslen -= 1;
 54    } else {
 55      stop = 1;
 56    }
 57
 58    while(input_cursor < cmdslen) {
 59      auto cmd, fullfilled; fullfilled = 0;
 60      cmd = *(input_buf + input_cursor) & 0xFF;
 61
 62      if ((!fullfilled) & (cmd == '>')) {
 63        if (cursor < MEMORY_LEN) cursor += 1;
 64        fullfilled = 1;
 65      }
 66      if ((!fullfilled) & (cmd == '<')) {
 67        if (cursor > 0) cursor -= 1;
 68        fullfilled = 1;
 69      }
 70      if ((!fullfilled) & (cmd == '+')) {
 71        if (memory[cursor] == 255) {
 72          memory[cursor] = 0;
 73        } else {
 74          memory[cursor] = memory[cursor] + 1;
 75        }
 76        fullfilled = 1;
 77      }
 78      if ((!fullfilled) & (cmd == '-')) {
 79        if (!memory[cursor]) {
 80          memory[cursor] = 255;
 81        } else {
 82          memory[cursor] = memory[cursor] - 1;
 83        }
 84        fullfilled = 1;
 85      }
 86      if ((!fullfilled) & (cmd == '.')) {
 87        printf("%c", memory[cursor]);
 88        fflush(0);
 89        fullfilled = 1;
 90      }
 91
 92      if (cmd == ',') {
 93        auto char_val; char_val = getchar();
 94        memory[cursor] = char_val;
 95        fullfilled = 1;
 96      }
 97
 98      if (cmd == '[') {
 99        if (!memory[cursor]) {
100          auto stack, jumped;
101          stack = 1; jumped = 0;
102          input_cursor += 1;
103
104          while((!jumped) & (input_cursor < cmdslen)) {
105            cmd = *(input_buf + input_cursor) & 0xFF;
106            if (cmd == '[') {
107              stack += 1;
108            }
109            if (cmd == ']') {
110              stack -= 1;
111              if (stack == 0) {
112                jumped = 1;
113                input_cursor -= 1;
114              }
115            }
116
117            input_cursor += 1;
118          }
119        }
120
121        fullfilled = 1;
122      }
123
124
125      if ((!fullfilled) & (cmd == ']')) {
126        if (memory[cursor]) {
127          auto stack, jumped;
128          stack = 1; jumped = 0;
129          input_cursor -= 1;
130
131          while((!jumped) & (input_cursor >= 0)) {
132            cmd = *(input_buf + input_cursor) & 0xFF;
133
134            if (cmd == ']') {
135              stack += 1;
136            }
137            if (cmd == '[') {
138              stack -= 1;
139              if (stack == 0) {
140                jumped = 1;
141              }
142            }
143
144            input_cursor -= 1;
145          }
146        }
147        fullfilled = 1;
148      }
149      if ((!fullfilled) & (cmd == '#')) {
150        cursor = 0;
151        memset(memory, 0, MEMORY_LEN*W);
152      }
153
154      if ((!fullfilled) & (cmd == '$') & (cmdslen == 1)) {
155        printf("MEMORY ADDRESS (0-29999): ");
156        auto addr_len, addr; addr_len = read(STDIN, addr_buf, 5);
157        if (addr_len > 0) {
158          *(addr_buf + addr_len - 1) = 0;
159          addr = atoi(addr_buf);
160          printf("MEMORY(+%d) -> %d\n", addr, memory[addr]);
161        }
162      }
163
164      input_cursor += 1;
165    }
166
167    printf("\n");
168  }
169}
170
171// Classic Hello world
172// >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.
173
174// Special commands:
175// - # -> to reset the memory and the cursor
176// - $ -> to inspect a memory address