1 | ;;; bfi446.rbf - 446-byte brainf*ck interpreter
|
---|
2 | ;
|
---|
3 | ; Coding this raped the brain of
|
---|
4 | ; (C) Dean Scarff <p00ya AT users . sf dot net>
|
---|
5 | ; 17 Aug 2003
|
---|
6 | ; Licensed under the Academic Free License version 2.0
|
---|
7 | ;
|
---|
8 | ; Stripping this file:
|
---|
9 | ;sed -e 's/;.*//' bfi446.rbf | tr -d '[:space:]' > bfi446.b
|
---|
10 | ; Pre-processing your own code 'src.bf':
|
---|
11 | ;cat src.bf | tr -d -c '+,.<>[]-' > src.b
|
---|
12 | ; Example use with guest code file 'src.bf':
|
---|
13 | ;cat src.bf | tr -d -c '+,.<>[]-' > src.b
|
---|
14 | ;printf '\0input' | cat src.b - | bfi bfi446.b
|
---|
15 | ; Use with manual code input:
|
---|
16 | ;printf 'code\0input' | bfi bfi446.b
|
---|
17 | ;
|
---|
18 | ; Conditional on the use of a conformant host interpreter, bfi446 conforms to
|
---|
19 | ; the 'non-existent' [BF1.3] with the following constraints:
|
---|
20 | ; o Pure, valid brainfuck code (no whitespace, no comments, no NULs).
|
---|
21 | ; Stripping as above is recommended.
|
---|
22 | ; o Code cannot start with a '[' (which is redundant anyway)
|
---|
23 | ; o If the host's tape-length L is finite, and N is the guest code size
|
---|
24 | ; Tape-length available = L/3 - N - 1
|
---|
25 | ; o The maximum nesting level of pretest loops is limited to the maximum
|
---|
26 | ; value of the implementation-defined integer.
|
---|
27 | ;
|
---|
28 |
|
---|
29 | ;;; CODE:
|
---|
30 |
|
---|
31 | ; *** Pre: Fill up the code buffer ***
|
---|
32 | >,[; Read code until NUL
|
---|
33 | >>++++++[<+++++[<--->-]>-]; (6*5*-3) pre-reduce by 90
|
---|
34 | ->,; flag walkers
|
---|
35 | ]
|
---|
36 | <[+<<<]>; @ [c=1]
|
---|
37 |
|
---|
38 | [; while ([c] != NULL)
|
---|
39 | [>+>+<<-]; mov [c] to [c+1] and [c+2]
|
---|
40 | ->; flag [c] -1 unfinished
|
---|
41 | ; * A.1: "[]" block
|
---|
42 | -[; not '['
|
---|
43 | --[; not ']'
|
---|
44 |
|
---|
45 | ; ** B.1: Execute "<>.-,+"
|
---|
46 | <+>; flag [c] finished
|
---|
47 | ; * B.1.1: Move into place
|
---|
48 | [>>>>+<<<<-]; mov remnant [c+1] to [c+5]
|
---|
49 | >>[>>[>>>-<<<+]>]; @ {-3}, remnant in {-1}
|
---|
50 | >+
|
---|
51 | [>[>>>-<<<+]>>]; @ [d+1], remnant in [d+2]
|
---|
52 |
|
---|
53 | ; ** A.2: "<>" block
|
---|
54 | ++++++[>+++++<-]->; 6*5, flag [d+1] = -1
|
---|
55 | +[; not '>'
|
---|
56 | ++[; not '<'
|
---|
57 |
|
---|
58 | ; ** A.3: "+,-." block
|
---|
59 | <+++++++[>+++<-]->; (-1+7)*3, flag [d+1] = -1 (unfinished)
|
---|
60 |
|
---|
61 | ; * B.1.2: Execute
|
---|
62 | -[; not '+'
|
---|
63 | -[; not ','
|
---|
64 | -[; not '-', therefore '.'
|
---|
65 | -< +<.> >; flag fin, exec, break
|
---|
66 | ]<[+<->]>; '-'
|
---|
67 | ]<[+<,>]>; ','
|
---|
68 | ]<[+<+>]>; '+'
|
---|
69 | ]<[+<<<+]>; '<' d-=3
|
---|
70 | ]<[>>>]; '>' d+=3
|
---|
71 |
|
---|
72 | -[+<<<-]; @ {-2}
|
---|
73 | <<<<[<<<]>; @ [c+1]
|
---|
74 |
|
---|
75 | ; ** B.2: ']'
|
---|
76 | ]<[; ']'
|
---|
77 | ++++>>---; [c] = ']', [c+3] = 0
|
---|
78 | <<<-[; c-=3, @ [c+2] stack counter
|
---|
79 | <<[<+>>+<-]; move [c] to [c-1] and [c+1]
|
---|
80 | >-[; not '['
|
---|
81 | --[; not ']'
|
---|
82 | >+<[+]
|
---|
83 | ]>--<; ']'
|
---|
84 | ]>+; '['
|
---|
85 |
|
---|
86 | <<<[>+<-]>>>; move [c-1] back to [c]
|
---|
87 | [<<<->>>+]<<<; move stack counter back
|
---|
88 | ]; [c+3] is matching bracket, @ [c+2]
|
---|
89 | <<[>>+<<-]; @ [c]
|
---|
90 | ]>; end ']'
|
---|
91 |
|
---|
92 | ; ** B.3: '['
|
---|
93 | ]<[+; '['
|
---|
94 | >>>[>>>]>; @ {-2}
|
---|
95 | +[>>>]-<; @ [d], [d+1] = -1
|
---|
96 | [; if [d]
|
---|
97 | >[+<<<-]<<<<[<<<]; @ [c]
|
---|
98 | ]>[; else (@ [c+1] or [d+1])
|
---|
99 | [+<<<-]<<<<[<<<]+; @ [c] = '['
|
---|
100 | >>[; c+=3, @ [c-1] stack counter
|
---|
101 | [>>>+<<<-]; mov [c-1] to [c+2]
|
---|
102 | >[>-<<->+]; mov [c] to [c+1] and [c-1]
|
---|
103 | >-[; not '['
|
---|
104 | --[; not ']'
|
---|
105 | >+<[+]
|
---|
106 | ]>--<; ']'
|
---|
107 | ]>+; '['
|
---|
108 | <<<[>+<-]; mov [c-1] to [c]
|
---|
109 | >>>; @ [c+2]
|
---|
110 | ]+++; [c] is matching bracket, @ [c+2] = 3
|
---|
111 | <]; end else, @ [c+1]
|
---|
112 | <[-]]; end '[', @ [c]
|
---|
113 |
|
---|
114 | ; * A.4: get ready for the next instruction
|
---|
115 | >>[<<+>>-]>; restore bk, c += 3
|
---|
116 | ]
|
---|
117 |
|
---|
118 | ;;; APPENDIX A: Memory layout
|
---|
119 |
|
---|
120 | ; [0] 0 _
|
---|
121 | ; [1] 1st instruction |
|
---|
122 | ; [2] GP |
|
---|
123 | ; [3] GP |
|
---|
124 | ; [4] 2nd instruction |
|
---|
125 | ; ... :
|
---|
126 | ; [c-1] stack|bk |
|
---|
127 | ; [c] current|fin|GP |
|
---|
128 | ; [c+1] operating copy | code
|
---|
129 | ; [c+2] bk |
|
---|
130 | ; [c+3] next instruction |
|
---|
131 | ; [c+4] |
|
---|
132 | ; [c+5] remnant |
|
---|
133 | ; ... :
|
---|
134 | ; {-6} last instruction |
|
---|
135 | ; {-5} GP |
|
---|
136 | ; {-4} GP |
|
---|
137 | ; {-3} NOP ¯
|
---|
138 | ; {-2} 0|+1 transistion
|
---|
139 | ; {-1} remnant|true _
|
---|
140 | ; {0} 1st data cell |
|
---|
141 | ; {1} -1 |
|
---|
142 | ; {2} |
|
---|
143 | ; {3} 2nd data cell |
|
---|
144 | ; ... :
|
---|
145 | ; [d-2] -1 |
|
---|
146 | ; [d-1] | data
|
---|
147 | ; [d] current data |
|
---|
148 | ; [d+1] 0|fin |
|
---|
149 | ; [d+2] remnant |
|
---|
150 | ; [d+3] data right |
|
---|
151 | ; [d+4] 0 |
|
---|
152 | ; ... V
|
---|
153 |
|
---|
154 | ;;; REFERENCES:
|
---|
155 | ; [BF1.3]
|
---|
156 | ; "The BrainF*** Language Specification v1.3",
|
---|
157 | ; Esoteric Non-existent Standards Institute, 01 January 2002
|
---|