Beispiel #1
0
    internal static CCNode BuildTree(Function f, params CCTypeSet[] args)
    {
        CCStack stack = new CCStack();

        foreach (CCTypeSet cts in args)
        {
            stack = stack.Push(cts);
        }
        CCNode start = f.Enter(stack, null, new CCNodeExit());

        for (;;)
        {
            int n = TO_EXPLORE.Count;
            if (n == 0)
            {
                break;
            }
            CCNode node = TO_EXPLORE[n - 1];
            TO_EXPLORE.RemoveAt(n - 1);
            node.update = false;
            node.Walk();
        }
        return(start);
    }
Beispiel #2
0
    internal void DoCall(string name)
    {
        /*
         * Make sure the next node exists. We also set its locals
         * to the current locals (the called function cannot
         * change our locals). Note that the stack is not set;
         * this will be done only when (if) one of the called
         * functions returns.
         */
        if (next == null)
        {
            next = GetNode(addr + 1);
        }
        next.MergeLocals(Locals);

        /*
         * Find all functions registered with the specified name.
         * If none is found, then we want a specific error message
         * (this is probably a typographic error in the function
         * name).
         */
        List <FunctionRegistration> r1 = Function.LookupAll(name);

        if (r1.Count == 0)
        {
            throw new Exception(string.Format("no such function: {0}", name));
        }

        /*
         * Find all functions that may match the types on the
         * stack.
         */
        List <FunctionRegistration> r2 =
            new List <FunctionRegistration>();
        int maxNum = 0;

        foreach (FunctionRegistration fr in r1)
        {
            if (Stack.MayMatch(fr.types))
            {
                r2.Add(fr);
                maxNum = Math.Max(maxNum, fr.types.Length);
            }
        }

        /*
         * For all combinations of types that may occur on the
         * stack, try to resolve the call; if any fails, then
         * report it as an error.
         * While doing so, we accumulate, for each reachable
         * function, the types that may appear on entry of
         * that function.
         */
        CCType[] combo = new CCType[maxNum];
        CCTypeSet.ComboEnumerator ce = new CCTypeSet.ComboEnumerator(
            Stack.GetTopElements(maxNum));
        XType[] xts = new XType[maxNum];
        SortedDictionary <Function, CCStack> targets =
            new SortedDictionary <Function, CCStack>();
        CCStack root  = Stack.Pop(maxNum);
        GStack  gtail = GStack.Make(root);

        calls = new List <DCall>();
        for (;;)
        {
            if (!ce.Next(combo))
            {
                break;
            }
            for (int i = 0; i < maxNum; i++)
            {
                xts[i] = combo[i].xType;
            }
            Function f      = Function.Resolve(name, r2, xts);
            CCStack  nstack = root.Push(combo);
            CCStack  ostack;
            if (targets.TryGetValue(f, out ostack))
            {
                targets[f] = CCStack.Merge(ostack, nstack);
            }
            else
            {
                targets[f] = nstack;
            }
            calls.Add(new DCall(GStack.Make(xts, gtail), f));
        }

        /*
         * We now have a complete list of reachable functions,
         * each with a corresponding entry stack; we know that
         * the call will always resolve to a single function. If
         * we are updating, we reuse the previous functions from
         * the dispatch variable if available. Note that an update
         * can only add new functions, not remove existing ones.
         */
        if (dispatch == null)
        {
            dispatch = new SortedDictionary <Function, CCNode>();
        }
        foreach (Function f in targets.Keys)
        {
            CCStack stack = targets[f];
            CCNode  onode;
            if (dispatch.TryGetValue(f, out onode))
            {
                onode.MergeStack(stack);
            }
            else
            {
                dispatch[f] = f.Enter(stack, cfi.Entry, next);
            }
        }
    }