
struct PlaceHolder : Shared
{
    PlaceHolder *sibling;                       // in list starting from UserFunction::phlist
    Node *currentvalue;                         // temp cached value given particular path/focus

    PlaceHolder() : sibling(NULL), currentvalue(NULL) {}

    int FindPos(PlaceHolder *tofind, int pos = 0) { return this==tofind ? pos : sibling ? sibling->FindPos(tofind, pos+1) : -1; }

    void CreateFunction2b()
    {
        Node *lca = LCA();                      // this is the node that we'll wrap the function around, and where the PH gets introduced first

        CreateUniqueName();

        UserFunction *puf = lca->fparent;
        if(puf && !puf->IsShared() && !currentvalue->HasOccurrencesOf(puf->phlist))             // there is already a single use function here, so we can simply add the PH to the list
        {
            Node *fc = puf->occurrences;
            currentvalue->sibling = fc->children;
            fc->children = currentvalue;        // we used this as temp storage to hold the PH value while scanning for duplicates
            currentvalue->parent = fc;
            currentvalue = NULL;
            sibling = puf->phlist;
            puf->phlist = this;
            throw (Node *)NULL;
        }
        else
        {
            UserFunction *uf = new UserFunction(lca, this);
            uf->CreateUniqueFunctionName();
            Node *fc = new Node(T_FUNCTIONCALL);
            uf->occurrences = fc;
            fc->uf = uf;
            fc->children = currentvalue;
            currentvalue->parent = fc;
            currentvalue = NULL;
            throw lca->ReplaceWith(fc, puf);
        }
    }

    static bool NameExists(wxString &tocheck, Node *n)
    {
        while(n)
        {
            if(n->fparent)
            {
                if(n->fparent->FindNameInPHs(tocheck)) return true;
                n = n->fparent->occurrences;    // any names that dominate this call must dominate all of them, hence we can follow any of em to the root
            }
            else
            {
                n = n->parent;
            }
        }
        return false;
    }

    void CreateUniqueName()
    {
        for(int i = 0; ; i++)
        {
            wxString newname = Identifier::GenName(false, i);
            loopoccurrences(n) if(NameExists(newname, n)) goto next;
            name = newname;
            return;
            next:;
        }
    }

    void IterContexts()
    {
        Node *p1 = occurrences->parent;
        if(!p1) return;

        int pos1, pos2;
        Vector<Node *> *matches = NULL;
        loopoccurrencesbutfirst(n)
        {
            Node *p2 = n->parent;
            if(p2 && p1->type==p2->type && p1->id==p2->id && p1->NumChildren()==p2->NumChildren())
            {
                pos1 = p1->FindPos(occurrences);
                pos2 = p2->FindPos(n);
                if(pos1==pos2)
                {
                    if(!matches)
                    {
                        matches = new Vector<Node *>;
                        matches->push() = occurrences;
                    }
                    matches->push() = n;
                }
            }
        }

        if(!matches) return;

        Node *keepph = NULL;
        Node *keeppar = NULL;

        loopv(i, (*matches))
        {
            Node *fc = new Node(T_FUNCTIONCALL);
            Node *n = (*matches)[i]->parent;
            ASSERT(n->parent || n->fparent);

            Node *phn = n->RemoveAndReparent(this, fc, pos1);
            if(keepph) delete phn;
            else keepph = phn;

            Node *nr = n->ReplaceWith(fc, n->fparent);
            ASSERT(!nr);

            if(keeppar) delete n;
            else keeppar = n;

            (*matches)[i] = fc;
        }

        ASSERT(keeppar && keepph);

        PlaceHolder *phl = (*matches)[0]->children->CreatePHs(&keeppar->children, keeppar);

        keeppar->InsertAt(keepph, pos1);

        UserFunction *uf = new UserFunction(keeppar, phl);

        loopv(i, (*matches))
        {
            Node *fc = (*matches)[i];
            fc->uf = uf;
            fc->nextoccurrence = uf->occurrences;
            uf->occurrences = fc;
        }

        for(; phl; phl = phl->sibling)
        {
            phl->CreateUniqueName();
        }

        uf->CreateUniqueFunctionName();

        matches->setsize_nd(0);
        delete matches;

        throw (Node *)NULL;                     // we have potentially reorganized parent tree, must escape from recursion
    }
};
