DEV Community

RocketMaker69
RocketMaker69

Posted on • Updated on

Making an interpreter in Python

Hello! today you and i are going to make an interpreter in Python! They're not that hard, also, we're making an interpreter, nod an interpreted language. So, to start off, we will need instructions that our interpreter understands. we will only have 3 instructions for now:

LOAD
ADD
PRINT_RES
Enter fullscreen mode Exit fullscreen mode

so, let's start making the interpreter!

class Interpreter:
    def __init__(self):
        self.stack = []
Enter fullscreen mode Exit fullscreen mode

we define an init() method which creates the stack. We will use the stack to add and remove numbers from it. that's what the LOAD() method will do:

def LOAD(self, num):
    self.stack.append(num)
Enter fullscreen mode Exit fullscreen mode

next is ADD(). ADD() takes the last 2 numbers from the stack and pushes their sum to the stack. Now let's make the ADD() method:

def ADD(self):
    b = self.stack.pop()
    a = self.stack.pop()
    self.stack.append(a + b)
Enter fullscreen mode Exit fullscreen mode

We invert a and b because pop() removes the last item of the stack, not the item at a specific index of the stack:

stack:
[
    6,   <--- This is a (popped after b)
    14   <--- And this is b (popped first)
]
Enter fullscreen mode Exit fullscreen mode

now we have to do the PRINT_RES() method, which prints the last item of the stack:

def PRINT_RES(self):
    r = self.stack.pop()
    print(r)
Enter fullscreen mode Exit fullscreen mode

finally, we will put it all together using a run() method:

def run(self, code):
    instructions = code["Instructions"]
    data         = code["Data"]
    for i in instructions:
        action, arg = i
        if action == "LOAD":
            self.LOAD(arg)
        if action == "ADD":
            self.ADD()
        if action == "PRINT_RES":
            self.PRINT_RES()
Enter fullscreen mode Exit fullscreen mode

We have one if statement for each instruction: one for LOAD, one for ADD and one for PRINT_RES. Here is the finished code:

class Interpreter:
    def __init__(self):
        self.stack = []

    def LOAD(self, num):
        self.stack.append(num)

    def ADD(self):
        b = self.stack.pop()
        a = self.stack.pop()
        self.stack.append(a + b)

    def PRINT_RES(self):
        r = self.stack.pop()
        print(r)

    def run(self, code):
        instructions = code["Instructions"]
        data         = code["Data"]
        for i in instructions:
            action, arg = i
            if action == "LOAD":
                self.LOAD(arg)
            if action == "ADD":
                self.ADD()
            if action == "PRINT_RES":
                self.PRINT_RES()
Enter fullscreen mode Exit fullscreen mode

With that, here is a test run:

code = {
    "Instructions": [
        ["LOAD", 6],
        ["LOAD", 14],
        ["ADD", None],
        ["PRINT_RES", None]
    ],
    "Data": []
}

i = Interpreter()
i.run(code)   # Output: 20
Enter fullscreen mode Exit fullscreen mode

And here, the same interpreter, written in JavaScript:

let interpreter = {
    "stack": [ ],
    "instr": [ ],
    "data" : [ ],

    "init": function (i, d) {
        this.instr = i;
        this.data  = d;
    },
    "load": function (x) { this.stack.push(x); },
    "add": function () {
         let b = this.stack.pop();
         let a = this.stack.pop();
         this.load(a + b);
    },
    "print": function () { console.log(this.stack.pop()); }
};
Enter fullscreen mode Exit fullscreen mode

And a test run:

let i = interpreter;
i.init(["print", "s0"], { "numbers": [], "strings": ["hi"], "names": [] });
Enter fullscreen mode Exit fullscreen mode

And with this, goodbye! Have a nice day of programming!

Top comments (0)