3 import crossplatform_ir_generation
5 class Environment(object):
6 def __init__(self, parent):
10 def __getitem__(self, symbol):
11 if symbol in self.symbols:
12 return self.symbols[symbol]
14 if self.parent is None:
15 raise Exception('Symbol "{}" not found'.format(symbol))
17 return self.parent[symbol]
19 def __setitem__(self, symbol, value):
20 self.symbols[symbol] = value
22 def builtin_print(*outputs):
23 outputs = list(outputs)
25 for i in range(len(outputs)):
28 if isinstance(output, bool):
29 outputs[i] = str(output).lower()
31 print(*outputs, end='')
33 BUILTIN_ENVIRONMENT = Environment(None)
34 BUILTIN_ENVIRONMENT.symbols = {
36 'pow': lambda base, exponent: pow(base, exponent),
37 'print': builtin_print,
41 def interpret(program):
42 environment = Environment(BUILTIN_ENVIRONMENT)
46 for i in range(len(program.entry_list)):
47 if isinstance(program.entry_list[i], crossplatform_ir_generation.CIRLabel):
48 if program.entry_list[i].label in label_indices:
49 raise Exception('Label already in labels')
51 label_indices[program.entry_list[i].label] = i
53 program_counter = label_indices['__main__'] + 1
57 while isinstance(program.entry_list[program_counter], crossplatform_ir_generation.CIRLabel):
60 instruction = program.entry_list[program_counter].instruction
61 argument = program.entry_list[program_counter].argument
63 if instruction in ('add', 'idiv', 'mod', 'mul', 'sub'):
67 assert isinstance(left, int)
68 assert isinstance(right, int)
70 if instruction == 'add':
72 elif instruction == 'idiv':
73 result = left // right
74 elif instruction == 'mod':
76 elif instruction == 'mul':
78 elif instruction == 'sub':
83 elif instruction in ('gt', 'gte', 'lt', 'lte'):
87 assert isinstance(left, int)
88 assert isinstance(right, int)
90 if instruction == 'gt':
92 elif instruction == 'gte':
93 result = left >= right
94 elif instruction == 'lt':
96 elif instruction == 'lte':
97 result = left <= right
101 elif instruction in ('eq', 'neq'):
106 if instruction == 'eq':
107 result = left == right
108 elif instruction == 'neq':
109 result = left != right
113 elif instruction == 'call':
114 assert isinstance(argument, int)
119 for i in range(argument):
120 args.append(stack.pop())
122 args = list(reversed(args))
124 stack.append(f(*args))
126 elif instruction == 'concat':
130 assert isinstance(left, str)
131 assert isinstance(right, str)
133 stack.append(left + right)
135 elif instruction == 'drop':
136 assert argument is None
139 elif instruction == 'end':
140 assert argument is None
143 elif instruction == 'get':
145 assert isinstance(argument, int)
147 assert isinstance(xs, list)
148 stack.append(xs[index])
150 elif instruction == 'jump_if_false':
151 program_counter = label_indices[argument]
153 elif instruction == 'list':
154 assert isinstance(argument, int)
158 for i in range(argument):
159 result.append(stack.pop())
161 stack.append(list(reversed(result)))
163 elif instruction == 'neg':
164 stack.append(-stack.pop())
166 elif instruction == 'pop':
167 assert argument.startswith('sym(')
168 assert argument.endswith(')')
169 environment[argument[4:-1]] = stack.pop()
171 elif instruction == 'push':
172 assert argument.startswith('sym(')
173 assert argument.endswith(')')
174 stack.append(environment[argument[4:-1]])
176 elif instruction == 'push_integer':
177 assert isinstance(argument, int)
178 stack.append(argument)
180 elif instruction == 'push_string':
181 assert argument.startswith('"')
182 assert argument.endswith('"')
183 stack.append(argument[1:-1].encode('utf-8').decode('unicode_escape'))
186 raise Exception('Instruction "{}" not supported (argument {}).'.format(