protected Node checkReachability(Term n) throws SemanticException {
    FlowGraph g = currentFlowGraph();
    if (g != null) {
      Collection peers = g.peers(n);
      if (peers != null && !peers.isEmpty()) {
        boolean isInitializer = (n instanceof Initializer);

        for (Iterator iter = peers.iterator(); iter.hasNext(); ) {
          FlowGraph.Peer p = (FlowGraph.Peer) iter.next();

          // the peer is reachable if at least one of its out items
          // is reachable. This would cover all cases, except that some
          // peers may have no successors (e.g. peers that throw an
          // an exception that is not caught by the method). So we need
          // to also check the inItem.
          if (p.inItem() != null) {
            DataFlowItem dfi = (DataFlowItem) p.inItem();
            // there will only be one peer for an initializer,
            // as it cannot occur in a finally block.
            if (isInitializer && !dfi.normalReachable) {
              throw new SemanticException(
                  "Initializers must be able to complete normally.", n.position());
            }

            if (dfi.reachable) {
              return n.reachable(true);
            }
          }

          if (p.outItems != null) {
            for (Iterator k = p.outItems.values().iterator(); k.hasNext(); ) {
              DataFlowItem item = (DataFlowItem) k.next();

              if (item != null && item.reachable) {
                // n is reachable.
                return n.reachable(true);
              }
            }
          }
        }

        // if we fall through to here, then no peer for n was reachable.
        n = n.reachable(false);

        // Compound statements are allowed to be unreachable
        // (e.g., "{ // return; }" or "while (true) S").  If a compound
        // statement is truly unreachable, one of its sub-statements will
        // be also and we will report an error there.

        if ((n instanceof Block && ((Block) n).statements().isEmpty())
            || (n instanceof Stmt && !(n instanceof CompoundStmt))) {
          throw new SemanticException("Unreachable statement.", n.position());
        }
      }
    }
    return n;
  }
  private Node translateSJInbranch(SJInbranch ib, QQ qq) {
    StringBuilder translation = new StringBuilder("{ ");
    Collection<Object> mapping = new LinkedList<Object>();

    String labVar = UniqueID.newID(SJ_INBRANCH_LABEL_FIELD_PREFIX);

    translation.append("%T %s = %E; ");
    mapping.add(qq.parseType(SJ_LABEL_CLASS));
    mapping.add(labVar);
    mapping.add(ib.inlabel());

    for (Iterator<SJInbranchCase> i = ib.branchCases().iterator(); i.hasNext(); ) {
      SJInbranchCase ibc = i.next();

      translation.append("if (%s.equals(%E)) { %LS } ");
      mapping.add(labVar);
      mapping.add(sjnf.StringLit(ib.position(), ibc.label().labelValue()));
      mapping.add(ibc.statements());

      if (i.hasNext()) {
        translation.append("else ");
      }
    }

    translation.append("else { throw new SJIOException(\"Unexpected inbranch label: \" + %s); }");
    mapping.add(labVar);

    // FIXME: need a final else case to better handle, if runtime monitoring is disabled,
    // non-sj-compatibility mode and in case of malicious peers.

    translation.append('}');

    return qq.parseStmt(translation.toString(), mapping.toArray());
  }
Exemple #3
0
  protected Node checkReachability(Term n) {
    FlowGraph g = currentFlowGraph();
    if (g != null) {
      Collection<FlowGraph.Peer> peers = g.peers(n, Term.EXIT);
      if (peers != null && !peers.isEmpty()) {
        boolean isInitializer = (n instanceof Initializer);

        for (FlowGraph.Peer p : peers) {
          // the peer is reachable if at least one of its out items
          // is reachable. This would cover all cases, except that some
          // peers may have no successors (e.g. peers that throw an
          // an exception that is not caught by the method). So we need
          // to also check the inItem.
          if (p.inItem() != null) {
            DataFlowItem dfi = (DataFlowItem) p.inItem();
            // there will only be one peer for an initializer,
            // as it cannot occur in a finally block.
            if (isInitializer && !dfi.normalReachable) {
              reportError(new Errors.InitializersMustCompleteNormally(n.position()));
            }

            if (dfi.reachable) {
              return n.reachable(true);
            }
          }

          if (p.outItems != null) {
            for (Item v : p.outItems.values()) {
              DataFlowItem item = (DataFlowItem) v;

              if (item != null && item.reachable) {
                // n is reachable.
                return n.reachable(true);
              }
            }
          }
        }

        // if we fall through to here, then no peer for n was reachable.
        n = n.reachable(false);
      }
    }
    return n;
  }
  // FIXME: does not integrate with recursive session method calls: recursionEnter/Exit and also
  // recurse do not match the control flow of recursive calls, and hence runtime type monitoring
  // does not work.
  private Node translateSJRecursion(SJRecursion r, QQ qq)
        // recursionEnter inserted by node factory, but translation is finished here..
      {
    SJSessionOperationExt soe = getSJSessionOperationExt(r);

    Position pos = r.position();

    Collection<Object> mapping = new LinkedList<Object>();

    String bname = getRecursionBooleanName(soe.targetNames(), r.label());

    mapping.add(bname);
    mapping.add(bname);

    String translation = "for (boolean %s = true; %s; ) { }";
    For f = (For) qq.parseStmt(translation, mapping.toArray());

    mapping.clear();

    r = (SJRecursion) r.inits(f.inits());
    r = (SJRecursion) r.cond(f.cond());

    List stmts = new LinkedList();

    stmts.addAll(r.body().statements());

    translation = "%s = %E;";
    mapping.add(bname);
    mapping.add(((Eval) stmts.remove(0)).expr()); // Factor out constant.

    Eval e = (Eval) qq.parseStmt(translation, mapping.toArray());

    stmts.add(0, e);

    r = (SJRecursion) r.body(sjnf.Block(pos, stmts));

    /*// Appending the recursion-exit hook. // Disabled to support delegation from within recursion scopes (socket will be null on recursion-exit).
    List<Local> targets = new LinkedList<Local>(); // FIXME: should be SJLocalSockets.

    for (String sjname : soe.targetNames()) // Unicast optimisation for SJRecursionExit is done within the NodeFactory method - this pass comes after SJUnicastOptimiser.
    {
    	targets.add(sjnf.Local(pos, sjnf.Id(pos, sjname))); // Would it be bad to instead alias the recursionEnter targets?
    }

    SJRecursionExit re = sjnf.SJRecursionExit(pos, targets); // Problem: the sockets argument array is not yet filled (for other (internal) basic operations, this was done earlier by SJSessionOperationParser)...

    re = (SJRecursionExit) SJVariableParser.parseSJSessionOperation(this, re); // ...Current fix: use those routines form those earlier passes.
    re = (SJRecursionExit) SJSessionOperationParser.fixSJBasicOperationArguments(this, re);*/

    // return sjnf.Block(pos, r, sjnf.Eval(pos, re));
    return sjnf.Block(pos, r);
  }