public void build() {
    declareMethod();

    ExceptionWrapper mainTryBlock = new ExceptionWrapper(codeModel, method.body(), context);
    for (Integer arity : primitive.getArity()) {
      JInvocation invocation = invoke("doApply").arg(context).arg(environment);

      for (int i = 0; i < arity; ++i) {
        invocation.arg(args.component(lit(i)));
      }
      mainTryBlock
          .body()
          ._if(JExpr.direct("args.length").eq(JExpr.lit(arity)))
          ._then()
          ._return(invocation);
    }

    mainTryBlock.catchEvalExceptions();
    mainTryBlock.catchRuntimeExceptions();
    mainTryBlock.catchExceptions();

    method
        .body()
        ._throw(
            JExpr._new(codeModel.ref(EvalException.class))
                .arg(lit(primitive.getName() + ": max arity is " + primitive.getMaxArity())));
  }
  public void buildVarArgs() {
    declareMethod();

    ExceptionWrapper mainTryBlock = new ExceptionWrapper(codeModel, method.body(), context);

    JvmMethod overload = primitive.getOverloads().get(0);
    VarArgParser parser = new VarArgParser(this, mainTryBlock.body(), overload);

    // convert the positional arguments
    convertArguments(parser.getArgumentProcessingBlock(), parser);

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

    CodeModelUtils.returnSexp(codeModel, mainTryBlock.body(), overload, invocation);

    mainTryBlock.catchEvalExceptions();
    mainTryBlock.catchRuntimeExceptions();
    mainTryBlock.catchExceptions();
  }