def __init__(self, atoms, code, imports, exports, literals, locals_, attributes, compile_info): self.load_opcodes() self.atoms = atoms self.code = code self.imports = imports self.exports = exports self.literals = literals self.locals = locals_ self.labels = dict() self.attributes = attributes self.compile_info = compile_info self.beam_writer = BeamWriter()
class BeamEncoder(): def __init__(self, atoms, code, imports, exports, literals, locals_, attributes, compile_info): self.load_opcodes() self.atoms = atoms self.code = code self.imports = imports self.exports = exports self.literals = literals self.locals = locals_ self.labels = dict() self.attributes = attributes self.compile_info = compile_info self.beam_writer = BeamWriter() def load_opcodes(self): self.opcodes = dict() for line in open(os.path.join(BEAM_FOLDER, 'common', 'opcodes.txt'),'r'): s = line.split('->') dx = s[1].strip(' ()\n').split(',') opname = dx[0].rstrip() opcode = int(s[0].strip()) self.opcodes[opname] = opcode def make_binary(self): self.assign_labels() self.assign_lambda_indexes() atoms = self.atoms imports = self.parse_imports(self.imports) exports = self.parse_exports(self.exports) lambdas = self.parse_lambdas(self.locals) code = self.parse_code(self.code) literals = self.literals locals_ = self.parse_locals(self.locals) attributes = self.attributes compile_info = self.compile_info beam_writer = self.beam_writer beam_writer.atom = atoms beam_writer.impT = imports beam_writer.expT = exports beam_writer.code = code beam_writer.funT = lambdas beam_writer.litT = literals beam_writer.locT = locals_ beam_writer.attr = attributes beam_writer.cInf = compile_info beam_writer.build_binary() def assign_labels(self): # ['recursive', 'tail_fac', 'erlang', '-', '*', 'module_info', 'get_module_info'] # exports = ['module_info/0', 'module_info/1', 'tail_fac/1'] # locals_ = ['tail_fac/2'] exports = self.exports locals_ = self.locals for fun in self.code: for instr in fun: if instr[0] == 'func_info': info = instr[1] if info[1] == None: # si tratta di una funzione di ordine superiore continue self.labels['%s/%d' % (info[1][1], info[2])] = fun[fun.index(instr) + 1][1][0] def assign_lambda_indexes(self): self.lambda_indexes = [l for l in self.locals if l.startswith('-')] def write(self, file_name): self.beam_writer.write(file_name) def parse_imports(self, imports): result = list() for imp in imports: s0 = imp.split(':') m = s0[0] s1 = s0[1].split('/') f = s1[0] a = s1[1] result.append((self.atoms.index(m) + 1, self.atoms.index(f) + 1, int(a))) return result def parse_exports(self, exports): # ['hello/0', 'module_info/0', 'module_info/1'] # [(3, 1, 6), (3, 0, 4), (2, 0, 2)] result = list() #label = 0 for fun in exports: #label += 2 s0 = fun.rsplit('/', 1) result.append((self.atoms.index(s0[0]) + 1, int(s0[1]), self.labels[fun])) #self.labeled_exports[fun] = label return result def parse_lambdas(self, locals_): # ['-dict_list_merge/1-fun-0-/2'] # [21, 2, 18, 0, 0, '\x01\x08<\xec'] result = list() lambdas = [l for l in locals_ if l.startswith('-')] for lam in lambdas: s0 = lam.rsplit('/', 1) result.append((self.atoms.index(s0[0]) + 1, int(s0[1]), self.labels[lam], self.lambda_indexes.index(lam), 0, 17317100)) #print result return result def parse_locals(self, locals_): # ['tail_fac/2'] # [(2, 2, 4)] result = list() for fun in locals_: s0 = fun.rsplit('/', 1) result.append((self.atoms.index(s0[0]) + 1, int(s0[1]), self.labels[fun])) return result def parse_code(self, code): setattr(self, self.atoms[0], self.module_name) fun_r = list() # print code for fun in code: instr_r = list() for instr in fun: param_r = list() for param in instr[1]: if type(param) is int: type_ = 'pure' val = param else: type_ = param[0] val = param[1] p = getattr(self, type_)(val) if type(p) in (tuple, list): param_r += p else: param_r.append(p) #print param_r instr_r.append((self.opcodes[instr[0]], param_r)) #print instr_r fun_r.append(instr_r) # aggiungo un int_code_end all'ultima funzione fun_r[-1].append((3, [])) #print fun_r return fun_r def pure(self, n): if n > 15: return (8, n) return n * 16 def atom(self, atom): #if atom.startswith('-'): n_atom = self.atoms.index(atom) if n_atom > 14: return (10, n_atom + 1) return (n_atom + 1) * 16 + 2 def x(self, n): return n * 16 + 3 def y(self, n): return n * 16 + 4 def f(self, n): if n > 15: return (13, n) else: return n * 16 + 5 def extfunc(self, fun): return self.pure(self.imports.index(fun)) def module_name(self, fun): if fun.startswith('-'): return self.lambda_indexes.index(fun) * 16 else: #return self.labels[fun] * 16 + 5 n = self.labels[fun] if n > 15: return (13, n) else: return n * 16 + 5 def integer(self, n): if n > 15: return (9, n) return n * 16 + 1 def literal(self, n): res = [71] p = self.pure(n) if type(p) == tuple: res += p else: res.append(p) return res def nil(self, n): return 2