Package org.renjin.invoke.codegen

Source Code of org.renjin.invoke.codegen.VarArgApplyBuilder

package org.renjin.invoke.codegen;

import com.sun.codemodel.*;
import org.renjin.invoke.model.JvmMethod;
import org.renjin.invoke.codegen.args.ArgConverterStrategies;
import org.renjin.invoke.model.PrimitiveModel;
import org.renjin.sexp.PairList;
import org.renjin.sexp.SEXP;
import org.renjin.sexp.Symbol;

import static com.sun.codemodel.JExpr.lit;

public class VarArgApplyBuilder extends ApplyMethodBuilder {


  private VarArgParser parser;

  public VarArgApplyBuilder(JCodeModel codeModel, JDefinedClass invoker, PrimitiveModel primitive) {
    super(codeModel, invoker, primitive);
  }

  @Override
  protected void apply(JBlock parent) {
    JvmMethod overload = primitive.getOverloads().get(0);

    parser = new VarArgParser(this, parent, overload);

    convertArgs(parser.getArgumentProcessingBlock());

    // try S3 dispatch
    genericDispatchStrategy.beforePrimitiveCalled(parent, parser, this, call);

    // finally invoke the underlying function
    JInvocation invocation = classRef(overload.getDeclaringClass()).staticInvoke(overload.getName());
    for(JExpression argument : parser.getArguments()) {
      invocation.arg(argument);
    }

    CodeModelUtils.returnSexp(codeModel, parent,  overload, invocation);
  }

  private void convertArgs(JBlock parent) {
    // convert the positional arguments
    int posIndex = 0;
    for(VarArgParser.PositionalArg posArgument : parser.getPositionalArguments()) {
      parent.assign(posArgument.getVariable(), convert(posArgument.getFormal(), nextArgAsSexp(posArgument.getFormal().isEvaluated())));
      genericDispatchStrategy.afterArgIsEvaluated(this, call, args, parent, posArgument.getVariable(), posIndex++);
    }

    // now we consume remaining args
    JWhileLoop loop = parent._while(hasMoreArguments());
    matchVarArg(loop.body());
  }

  private void matchVarArg(JBlock block) {
    JVar node = block.decl(classRef(PairList.Node.class), "node", argumentIterator.invoke("nextNode"));
    JVar value = block.decl(classRef(SEXP.class), "value", node.invoke("getValue"));
    JVar evaluated = block.decl(classRef(SEXP.class), "evaluated");

    JConditional ifMissing = block._if(value.eq(classRef(Symbol.class).staticRef("MISSING_ARG")));
    ifMissing._then().assign(evaluated, value);
    ifMissing._else().assign(evaluated, context.invoke("evaluate").arg(value).arg(environment));

    JConditional unnamed = block._if(node.invoke("hasName").not());

    // if the argument is unnamed, just add to the var arg list
    unnamed._then().invoke(parser.getVarArgBuilder(), "add").arg(evaluated);

    // otherwise we may need to check it against named flags
    JBlock namedBlock = unnamed._else();
    JVar name = namedBlock.decl(classRef(String.class), "name", node.invoke("getName"));

    IfElseBuilder matchSequence = new IfElseBuilder(namedBlock);
    for(JvmMethod.Argument namedFlag : parser.getNamedFlags().keySet()) {
      matchSequence._if(lit(namedFlag.getName()).invoke("equals").arg(name))
              .assign(parser.getNamedFlags().get(namedFlag), convert(namedFlag, evaluated));

    }
    matchSequence._else().invoke(parser.getVarArgBuilder(), "add").arg(name).arg(evaluated);
  }

  private JExpression hasMoreArguments() {
    return argumentIterator.invoke("hasNext");
  }

  private JExpression convert(JvmMethod.Argument formal, JExpression sexp) {
    return ArgConverterStrategies.findArgConverterStrategy(formal).convertArgument(this, sexp);
  }

}
TOP

Related Classes of org.renjin.invoke.codegen.VarArgApplyBuilder

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.