File: tla.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (178 lines) | stat: -rw-r--r-- 4,321 bytes parent folder | download | duplicates (8)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

from rpython.rlib.jit import JitDriver


class W_Object:

    def getrepr(self):
        """
        Return an RPython string which represent the object
        """
        raise NotImplementedError 

    def is_true(self):
        raise NotImplementedError

    def add(self, w_other):
        raise NotImplementedError



class W_IntObject(W_Object):

    def __init__(self, intvalue):
        self.intvalue = intvalue

    def getrepr(self):
        return str(self.intvalue)

    def is_true(self):
        return self.intvalue != 0

    def add(self, w_other):
        if isinstance(w_other, W_IntObject):
            sum = self.intvalue + w_other.intvalue
            return W_IntObject(sum)
        else:
            raise OperationError

    def sub(self, w_other):
        if isinstance(w_other, W_IntObject):
            sum = self.intvalue - w_other.intvalue
            return W_IntObject(sum)
        else:
            raise OperationError

class W_StringObject(W_Object):

    def __init__(self, strvalue):
        self.strvalue = strvalue

    def getrepr(self):
        return self.strvalue

    def is_true(self):
        return len(self.strvalue) != 0


class OperationError(Exception):
    pass

# ____________________________________________________________

OPNAMES = []
HASARG = []

def define_op(name, has_arg=False):
    globals()[name] = len(OPNAMES)
    OPNAMES.append(name)
    HASARG.append(has_arg)

define_op("CONST_INT", True)
define_op("POP")
define_op("ADD")
define_op("RETURN")
define_op("JUMP_IF", True)
define_op("DUP")
define_op("SUB")
define_op("NEWSTR", True)


# ____________________________________________________________

def get_printable_location(pc, bytecode):
    op = ord(bytecode[pc])
    name = OPNAMES[op]
    if HASARG[op]:
        arg = str(ord(bytecode[pc + 1]))
    else:
        arg = ''
    return "%s: %s %s" % (pc, name, arg)

jitdriver = JitDriver(greens=['pc', 'bytecode'],
                      reds=['self'],
                      virtualizables=['self'],
                      get_printable_location=get_printable_location)

class Frame(object):
    _virtualizable_ = ['stackpos', 'stack[*]']
    
    def __init__(self, bytecode):
        self.bytecode = bytecode
        self.stack = [None] * 8
        self.stackpos = 0

    def push(self, w_x):
        self.stack[self.stackpos] = w_x
        self.stackpos += 1

    def pop(self):
        stackpos = self.stackpos - 1
        assert stackpos >= 0
        self.stackpos = stackpos
        res = self.stack[stackpos]
        self.stack[stackpos] = None
        return res

    def interp(self):
        bytecode = self.bytecode
        pc = 0

        while pc < len(bytecode):
            jitdriver.jit_merge_point(bytecode=bytecode, pc=pc, self=self)
            opcode = ord(bytecode[pc])
            pc += 1

            if opcode == CONST_INT:
                value = ord(bytecode[pc])
                pc += 1
                w_z = W_IntObject(value)
                self.push(w_z)

            elif opcode == POP:
                self.pop()

            elif opcode == DUP:
                w_x = self.pop()
                self.push(w_x)
                self.push(w_x)

            elif opcode == ADD:
                w_y = self.pop()
                w_x = self.pop()
                w_z = w_x.add(w_y)
                self.push(w_z)

            elif opcode == SUB:
                w_y = self.pop()
                w_x = self.pop()
                w_z = w_x.sub(w_y)
                self.push(w_z)
            elif opcode == JUMP_IF:
                target = ord(bytecode[pc])
                pc += 1
                w_x = self.pop()
                if w_x.is_true():
                    pc = target
                    jitdriver.can_enter_jit(bytecode=bytecode, pc=pc, self=self)

            elif opcode == NEWSTR:
                char = bytecode[pc]
                pc += 1
                w_z = W_StringObject(char)
                self.push(w_z)

            elif opcode == RETURN:
                w_x = self.pop()
                assert self.stackpos == 0
                return w_x

            else:
                assert False, 'Unknown opcode: %d' % opcode


def run(bytecode, w_arg):
    frame = Frame(bytecode)
    frame.push(w_arg)
    w_result = frame.interp()
    return w_result