Beispiel #1
0
  @Override
  protected final Expr unLambda(final Name n) {
    final Map<Name, Expr> map = defs.unLambda().getMap();
    final LinkedList<Set<Name>> sorted = topoSort(map);

    Expr ex = getBody();
    for (final Set<Name> names : sorted) {
      if (names.size() == 1) {
        final Name nm = names.iterator().next();
        final Expr def = map.get(nm);
        final int uses = ex.numOfUses(nm);
        if (uses == 0) {
          // name unused, ignore it
          log.info("removing unused definition " + nm + ": " + def);
        } else if (uses == 1 || def instanceof Value) {
          // can be inlined
          log.info("inlining " + nm + ": " + def);
          ex = ex.inline(nm, def);
        } else {
          ex = App.create(new Lambda(nm.toString(), ex), map.get(nm));
        }
      } else {
        final Name[] na = names.toArray(new Name[names.size()]);

        Expr funs = NIL, res = K.app(ex);
        for (final Name element : na) {
          funs = CONS.app(map.get(element), funs);
        }

        funs = K.app(funs);

        for (final Name element : na) {
          funs = U.app(new Lambda(element.toString(), funs));
          if (res.hasFree(element)) {
            res = U.app(new Lambda(element.toString(), res));
          } else {
            // name unused, ignore it
            log.info("rewriting unused name: U { " + element + " -> f } ==> (f . tl)");
            final Name nm = Name.createName();
            res = new Lambda(nm.toString(), App.create(res, TL.app(nm)));
          }
        }

        ex = App.create(res, Y.app(funs));
      }
    }

    return ex.unLambda(n);
  }