Package org.renjin.compiler

Source Code of org.renjin.compiler.PackageLoaderCompiler

package org.renjin.compiler;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.renjin.invoke.codegen.WrapperGenerator2;
import org.renjin.sexp.Closure;
import org.renjin.sexp.Environment;
import org.renjin.sexp.SEXP;
import org.renjin.sexp.Symbol;


public class PackageLoaderCompiler implements Opcodes {

 
  private static final int THIS = 0;
  private static final int CONTEXT = 1;
  private static final int ENVIRONMENT = 2;


  public static byte[] compile(String packageName, Environment packageEnvironment) {

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, CompiledNames.loaderClassName(packageName), null,
        "java/lang/Object", new String[] { "org/renjin/compiler/runtime/PackageLoader" });

    writeInit(cw);
    writeLoadMethod(cw, packageName, packageEnvironment);
   
    return cw.toByteArray();
  }

  private static void writeInit(ClassWriter cw) {
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, THIS);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();   
  }

  private static void writeLoadMethod(ClassWriter cw, String packageName, Environment rho) {
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "load",
        "(Lorg/renjin/eval/Context;Lorg/renjin/sexp/Environment;)V", null, null);
    mv.visitCode();

    for(Symbol symbol : rho.getSymbolNames()) {
      SEXP value = rho.getVariable(symbol);
      try {
        if(value instanceof Closure) {
          storeClosure(mv, packageName, symbol);       
        } else {
          storeConstant(mv, symbol, rho.getVariable(symbol));
        }
      } catch(Exception e) {
        throw new RuntimeException("Error generating code for '" + symbol + "'", e);
      }
    }
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
  }


  private static void storeClosure(MethodVisitor mv, String packageName, Symbol symbol) {
    mv.visitVarInsn(ALOAD, ENVIRONMENT);
    mv.visitLdcInsn(symbol.getPrintName());
    mv.visitTypeInsn(NEW, "org/renjin/compiler/runtime/PromisedFunction");
    mv.visitInsn(DUP);
    mv.visitVarInsn(ALOAD, CONTEXT);
    mv.visitVarInsn(ALOAD, ENVIRONMENT);
    mv.visitLdcInsn(functionClassName(packageName, symbol));
    mv.visitMethodInsn(INVOKESPECIAL, "org/renjin/compiler/runtime/PromisedFunction", "<init>",
        "(Lorg/renjin/eval/Context;Lorg/renjin/sexp/Environment;Ljava/lang/String;)V");
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/renjin/sexp/Environment", "setVariable",
        "(Ljava/lang/String;Lorg/renjin/sexp/SEXP;)V");
  }

  private static void storeConstant(MethodVisitor mv, Symbol symbol, SEXP value) {
    mv.visitVarInsn(ALOAD, ENVIRONMENT);
    mv.visitLdcInsn(symbol.getPrintName());
    ConstantGeneratingVisitor cgv = new ConstantGeneratingVisitor(mv);
    value.accept(cgv);
  }
 
  private static String functionClassName(String packageName, Symbol symbol) {
    return packageName.replace('/', '.') + "." + WrapperGenerator2.toJavaName("", symbol.getPrintName());
  }
}
TOP

Related Classes of org.renjin.compiler.PackageLoaderCompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.