Exemple #1
0
 @Override
 public void GlobalVariable(GlobalVariable variable) {
   encoder.encode(variable.getName());
 }
  private boolean computeScopeFlags(boolean receivesClosureArg, List<Instr> instrs) {
    for (Instr i : instrs) {
      Operation op = i.getOperation();
      if (op == Operation.RECV_CLOSURE) {
        receivesClosureArg = true;
      } else if (op == Operation.ZSUPER) {
        this.canCaptureCallersBinding = true;
        this.usesZSuper = true;
      } else if (i instanceof CallBase) {
        CallBase call = (CallBase) i;

        if (call.targetRequiresCallersBinding()) this.bindingHasEscaped = true;

        if (call.canBeEval()) {
          this.usesEval = true;

          // If this method receives a closure arg, and this call is an eval that has more than 1
          // argument,
          // it could be using the closure as a binding -- which means it could be using pretty much
          // any
          // variable from the caller's binding!
          if (receivesClosureArg && (call.getCallArgs().length > 1)) {
            this.canCaptureCallersBinding = true;
          }
        }
      } else if (op == Operation.GET_GLOBAL_VAR) {
        GlobalVariable gv = (GlobalVariable) ((GetGlobalVariableInstr) i).getSource();
        String gvName = gv.getName();
        if (gvName.equals("$_")
            || gvName.equals("$~")
            || gvName.equals("$`")
            || gvName.equals("$'")
            || gvName.equals("$+")
            || gvName.equals("$LAST_READ_LINE")
            || gvName.equals("$LAST_MATCH_INFO")
            || gvName.equals("$PREMATCH")
            || gvName.equals("$POSTMATCH")
            || gvName.equals("$LAST_PAREN_MATCH")) {
          this.usesBackrefOrLastline = true;
        }
      } else if (op == Operation.PUT_GLOBAL_VAR) {
        GlobalVariable gv = (GlobalVariable) ((PutGlobalVarInstr) i).getTarget();
        String gvName = gv.getName();
        if (gvName.equals("$_") || gvName.equals("$~")) usesBackrefOrLastline = true;
      } else if (op == Operation.MATCH || op == Operation.MATCH2 || op == Operation.MATCH3) {
        this.usesBackrefOrLastline = true;
      } else if (op == Operation.BREAK) {
        this.hasBreakInstrs = true;
      } else if (i instanceof NonlocalReturnInstr) {
        this.hasNonlocalReturns = true;
      } else if (i instanceof DefineMetaClassInstr) {
        // SSS: Inner-classes are defined with closures and
        // a return in the closure can force a return from this method
        // For now conservatively assume that a scope with inner-classes
        // can receive non-local returns. (Alternatively, have to inspect
        // all lexically nested scopes, not just closures in computeScopeFlags())
        this.canReceiveNonlocalReturns = true;
      }
    }

    return receivesClosureArg;
  }