/** -*- tab-width: 4 -*- * This file is part of Erjang - A JVM-based Erlang VM * * Copyright (c) 2010 by Trifork * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package erjang.beam.repr; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.logging.Level; import java.util.logging.Logger; import erjang.EAtom; import erjang.EObject; import erjang.ERT; import erjang.ESeq; import erjang.ESmall; import erjang.ETuple; import erjang.beam.BeamFileData; import erjang.beam.CodeAtoms; import erjang.beam.ModuleVisitor; import erjang.beam.loader.Rewriter; public class ModuleRepr implements BeamFileData { static Logger log = Logger.getLogger("erjang.beam"); private EAtom moduleName; private final CodeTables ct; private final FunctionInfo[] exports; private final FunctionRepr[] functions; private ESeq attributes; private ESeq compilation_info; public ModuleRepr(CodeTables ct, EAtom moduleName, FunctionInfo[] exports, ESeq attributes, ESeq comp_info, FunctionRepr[] functions) { this.moduleName = moduleName; this.ct = ct; this.exports = exports; this.attributes = attributes; this.compilation_info = comp_info; this.functions = functions; } public void accept(ModuleVisitor v) { v.visitModule(moduleName); visit_exports(v); visit_attributes(v); visit_compile(v); try { for (FunctionRepr fun : functions) fun.declare(v); for (FunctionRepr fun : functions) fun.accept(v); } catch (RuntimeException e) { log.severe("ModuleRepr: Error in traversal: "+e.getMessage()); log.log(Level.FINE, "details: ", e); throw(e); } finally { v.visitEnd(); } } private void visit_attributes(ModuleVisitor v) { for (ESeq exp = (ESeq) attributes; exp != ERT.NIL; exp = exp.tail()) { ETuple attr = (ETuple) exp.head(); v.visitAttribute((EAtom) attr.elm(1), attr.elm(2)); } } private void visit_compile(ModuleVisitor v) { for (ESeq exp = (ESeq) compilation_info; exp != ERT.NIL; exp = exp.tail()) { ETuple attr = (ETuple) exp.head(); v.visitCompile((EAtom) attr.elm(1), attr.elm(2)); } } private void visit_exports(ModuleVisitor v) { for (FunctionInfo exp : exports) { v.visitExport(exp.fun, exp.arity, exp.label); } } //==================== Symbolic form ==================== public ETuple toSymbolic() { return ETuple.make(CodeAtoms.BEAM_FILE_ATOM, moduleName, symbolicExportList(), symbolicAttributes(), compilation_info, symbolicCode()); } public EObject symbolicAttributes() { // Sort the attributes to make them comparable to beam_disasm's output: EObject[] attrs = attributes.toArray(); Arrays.sort(attrs, EObject.ERLANG_ORDERING); return ESeq.fromArray(attrs); } public ESeq symbolicExportList() { ArrayList<EObject> symExports = new ArrayList<EObject>(exports.length); int i=0; for (FunctionInfo f : exports) { symExports.add(ETuple.make(f.fun, new ESmall(f.arity), new ESmall(f.label))); } Collections.sort(symExports, EObject.ERLANG_ORDERING); return ESeq.fromList(symExports); } public ESeq symbolicCode() { ArrayList<ETuple> symFunctions = new ArrayList<ETuple>(functions.length); for (FunctionRepr fun : functions) { symFunctions.add(fun.toSymbolic()); } return ESeq.fromList(symFunctions); } public void rewrite(Rewriter rw) { for (FunctionRepr f : functions) { f.rewrite(rw); } } }