Befunge++

Heya, I got interested in esoteric languages again, so I decided to make a Befunge interpreter (with some extra features). First, I would have to build the interpreter for the standard Befunge, then add new functions.

So far, I have this code (it consists entirely of one function and a loop, the function checks the characters and the loop makes the pointer move):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>
#include <bitset>
#include <stack>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#define IS_NUM(x) (x>=48 && x<=57)

using namespace std;

bool ComeAcross(char c, stack<int>& s, vector<string>& grid, bool& StringMode, bool& Trampoline, bitset<2>& Direction)
{
    if(!StringMode)
    {
        int a=s.top();

        // Program end
        if (c == '@') return false;

        // String mode
        else if (c == '\"') StringMode = true;

        // Input
        else if (c == '&'); // INPUT A NUMBER
        else if (c == '~'); // INPUT A CHARACTER (ASCII value)

        // Direction changers
        else if (c == '>') Direction.reset();
        else if (c == '^') Direction.set(0),Direction.reset(1);
        else if (c == '<') Direction.set(1),Direction.reset(0);
        else if (c == 'v') Direction.set();
        else if (c == '?')
        {   Direction.reset();
            if(rand()%100 < 49) Direction.set(0);
            if(rand()%100 < 49) Direction.set(1);}
        else if (c == '#') Trampoline = true;

        // Value pushing
        else if (IS_NUM(c)) s.push(c - 48);

        else if (s.size()>0)
        {
            // Basic stack editing
            if (c == ':') {s.push(a);}
            else if (c == '$') {s.pop();}

            // Printing
            else if (c == '.') {cout << int(a);s.pop();}
            else if (c == ',') {cout << char(a);s.pop();}

            // If's
            else if (c == '|') {s.pop();Direction.set(0,1);Direction.set(1,a == 0);}
            else if (c == '_') {s.pop();Direction.set(0,0);Direction.set(1,a == 0);}

            else if (s.size()>1)
            {   // Basic arithmetic
                if (c == '+') {s.pop();a+=s.top();s.pop();s.push(a);}
                else if (c == '-') {s.pop();a-=s.top();s.pop();s.push(a);}
                else if (c == '*') {s.pop();a*=s.top();s.pop();s.push(a);}
                else if (c == '/') {s.pop();a/=s.top();s.pop();s.push(a);}
                else if (c == '%') {s.pop();a%=s.top();s.pop();s.push(a);}
                else if (c == '`') {s.pop();a=s.top()>a;s.pop();s.push(a);}

                // values
                else if (c == 'g') {s.pop();a=grid[a][s.top()];s.pop();s.push(a);}
                if (s.size()>2 && c == 'p') {}
            }}
    }
    else
    {
        if (c == '\"') StringMode = false;
        else s.push(c);
    }
    return true;
}

int main()
{
    srand(time(0));
    stack<int> BefungeStack;
    vector<string> BefungeGrid;
    bitset<2> BefungeDirection(0);

    BefungeGrid.push_back(string("12+.@"));


    int x = 0, y = 0;
    bool StringMode = 0;
    bool Trampoline = 0;
    while(ComeAcross(BefungeGrid[y][x], BefungeStack, BefungeGrid, StringMode, Trampoline, BefungeDirection))
    {
        if (BefungeDirection[0]==false) x-=(2*BefungeDirection[1]-1)*(1+Trampoline);
        else                            y+=(2*BefungeDirection[1]-1)*(1+Trampoline);

        if(y<0) y = BefungeStack.size()-1;
    }
}


But this throws a segfault. What did I do wrong?
But this throws a segfault.

In which line?

Also, for IS_NUM, why use a macro and 48 and 57 instead of the corresponding character literals?
Well, the code compiles fine, but it throws that at runtime. I guess I should debug it somehow, but I have no experience on that whatsoever. :/
Press Run/Debug (or similar) or F8/F11 in your IDE or start your program from the command line with gdb.
It will then show you the line the segmentation fault occurred in and the callstack. It will also allow you to inspect the value of any variable at the time of crash.
Last edited on
I'm using Code::Blocks at the moment, do you know how it works on that? :/ The codeblocks wiki isn't really being helpful.

EDIT:
I made a few changes to the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <bitset>
#include <stack>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
    srand(time(0));
    stack<int> s;
    vector<string> g;
    bitset<2> d(0);

    g.push_back(string("12+.@"));


    int x = 0, y = 0;
    bool StringMode = 0;
    bool Trampoline = 0;
    while(true)
    {
        // TILECHECKING
        char c = g[y][x];
        if(!StringMode)
        {
            int a=s.top();
            // Program end
            if (c == '@') break;

            // String mode
            else if (c == '\"') StringMode = true;

            // Input
            else if (c == '&'); // INPUT A NUMBER
            else if (c == '~'); // INPUT A CHARACTER (ASCII value)

            // Direction changers
            else if (c == '>') d.reset();
            else if (c == '^') d.set(0),d.reset(1);
            else if (c == '<') d.set(1),d.reset(0);
            else if (c == 'v') d.set();
            else if (c == '?')
            {   d.reset();
                if(rand()%100 < 49) d.set(0);
                if(rand()%100 < 49) d.set(1);}
            else if (c == '#') Trampoline = true;

            // Value pushing
            else if (c >= '0' && c <= '9') s.push(c - '0');

            else if (s.size()>0)
            {
                // Basic stack editing
                if (c == ':') {s.push(a);}
                else if (c == '$') {s.pop();}

                // Printing
                else if (c == '.') {cout << int(a);s.pop();}
                else if (c == ',') {cout << char(a);s.pop();}

                // If's
                else if (c == '|') {s.pop();d.set(0,1);d.set(1,a == 0);}
                else if (c == '_') {s.pop();d.set(0,0);d.set(1,a == 0);}

                else if (s.size()>1)
                {   // Basic arithmetic
                         if (c == '+') {s.pop();s.top() += a;}
                    else if (c == '-') {s.pop();a-=s.top();s.pop();s.push(a);}
                    else if (c == '*') {s.pop();s.top() *= a;}
                    else if (c == '/') {s.pop();a/=s.top();s.pop();s.push(a);}
                    else if (c == '%') {s.pop();a%=s.top();s.pop();s.push(a);}
                    else if (c == '`') {s.pop();a=s.top()>a;s.pop();s.push(a);}

                    // values
                    else if (c == 'g') {s.pop();a=g[a][s.top()];s.pop();s.push(a);}
                    else if (s.size()>2 && c == 'p') {}
                }}
        }
        else
        {
            if (c == '\"') StringMode = false;
            else s.push(c);
        }

        // MOVEMENT
        if (d[0]==false) x-=(2*d[1]-1)*(1+Trampoline);
        else             y+=(2*d[1]-1)*(1+Trampoline);

        if(y<0) y = s.size()-1;
    }
}
Last edited on
I'm using Code::Blocks at the moment, do you know how it works on that? :/

Debug/Start (isn't it obvious?) or press F8.
Well, sure, the debugger starts, but it hangs at rule 30 and doesn't go any further, no matter what button I press (from continue, next line and next instruction) it doesn't do ANYTHING besides printing that it is going to continue (but it still hangs).
Well, line 31 is where the program crashes (because you're calling top() on an empty stack), so you can't continue.
The debugger further shows that x=0, y=0 and c='1', so this means the crash already happens for the first character (which isn't surprising, looking at the code).
Thanks, that (and some fixes) did the trick! I'm now going to focus on adding new features. One of them will be tunneling. Much like a normal tunnel, it would ignore characters, but this one would, just like the string, apply this functionality from one element till the next one. In that manner, it can be used to create comment sections or just to move over a block of code without editing it. The new character for this would be T (for tunnel, also one of my initials :P).
Topic archived. No new replies allowed.