Making an interpreter in Python
Tags: python
Published: 2021-09-25 09:27:06

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
```

so, let's start making the interpreter!

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

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:

```python
def LOAD(self, num):
    self.stack.append(num)
```
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:

```python
def ADD(self):
    b = self.stack.pop()
    a = self.stack.pop()
    self.stack.append(a + b)
```
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)
]
```

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

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

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

```python
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()
```
We have one if statement for each instruction: one for LOAD, one for ADD and one for PRINT_RES. Here is the finished code:
```python
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()
```



With that, here is a test run:
```python
code = {
    "Instructions": [
        ["LOAD", 6],
        ["LOAD", 14],
        ["ADD", None],
        ["PRINT_RES", None]
    ],
    "Data": []
}

i = Interpreter()
i.run(code)   # Output: 20
```
And here, the same interpreter, written in JavaScript: ```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()); }
};
```
And a test run: ```javascript
let i = interpreter;
i.init(["print", "s0"], { "numbers": [], "strings": ["hi"], "names": [] });
```
And with this, goodbye! Have a nice day of programming!