Package abstrasy.pcfx

Source Code of abstrasy.pcfx.PCFx_do

package abstrasy.pcfx;


import abstrasy.Heap;
import abstrasy.Interpreter;
import abstrasy.Node;
import abstrasy.PCoder;
import abstrasy.StaticHeap;

import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.StdErrors;


/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
*   http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/

public class PCFx_do extends PCFx {

    public PCFx_do() {
    }

    private final static void _clear_closure_(Heap closure){ if (closure.isLoaded()) closure.clear(); }
   
    final private static boolean xPC_Condition(Heap local, Node cnode) throws Exception {
        boolean test = false;
        _clear_closure_(local);
        test = Node.isTrueEquivalent(cnode.exec(true));
        return test;
    }

    public Node eval(Node startAt) throws Exception {
        //System.out.println("loop WHILE:"+ startAt.nodeToString());
        // forme : (do {...} while {...})
        // ou    : (do {...} until {...})
        // ou    : (do {...} forever)
        //          0  1     2     3
        startAt.isGoodArgsCnt(3, 4);
        Node cnode = null;
        Node modenode = null;
        Node xnode = null;
        if (startAt.size() == 4) {
            // forme (do {...} while {...}) et (do {...} until {...})
            cnode = startAt.getSubNode(3, Node.TYPE_LAZY);
            modenode = startAt.getSubNode(2, Node.TYPE_PCODE);
            if (!(modenode.isPCode(PCoder.PC_WHILE) || modenode.isPCode(PCoder.PC_UNTIL))) {
                throw new InterpreterException(StdErrors.Syntax_error);
            }
            boolean untilLoop = modenode.isPCode(PCoder.PC_UNTIL);
            Node enode = startAt.getSubNode(1, Node.TYPE_LAZY);

            Interpreter interpreter = Interpreter.mySelf();
            StaticHeap global = interpreter.getGLOBAL();
            boolean oldCanLoop = interpreter.isCanLoop();
            boolean oldInLoop = interpreter.isInLoop();
            interpreter.setCanLoop(true);
            interpreter.setInLoop(true);
            //
            int href = global.size();
            int slock = global.getOffset();
           
            Heap local=new Heap();
            global.push(local);
            //
           
            /*
             * Correction du 10 mai 2011:
             * =========================
             *    Les boucles du type do{...} s'arrête dès qu'un résultat est retourné. Cela ne signifie
             *    bien entendu pas que la condition qui permet l'itération n'est pas vérifiée. Toutefois,
             *    comme les boucle du type do{...} ne peuvent retourner qu'un seul résultat, il est inutile
             *    de relancer l'itération suivante ddès qu'un résultat est fourni. Ainsi, pour permettre
             *    de continuer la boucle, il est possible de placer le résultat dans une variable et non de
             *    la retourner directement comme résultat.
             *   
             */
            boolean loop = true;
            while (loop) {
                _clear_closure_(local);
                xnode = enode.exec(true);
                loop = xnode==null && interpreter.isCanIterate() && (untilLoop ? !xPC_Condition(local, cnode): xPC_Condition(local, cnode));
            }
            //
            global.pull();

            if (global.size() != href) {
                global.setOffset(slock);
                global.setSize(href); // restaurer le heap à la bonne taille
            }
            //
            interpreter.consumeBreakCode_onLoop();
            interpreter.setCanLoop(oldCanLoop);
            interpreter.setInLoop(oldInLoop);
            return xnode;

        }
        else {
            // forme (do {...} forever)
            modenode = startAt.getSubNode(2, Node.TYPE_PCODE);
            if (!modenode.isPCode(PCoder.PC_FOREVER)) {
                throw new InterpreterException(StdErrors.Syntax_error);
            }
        }
        Node enode = startAt.getSubNode(1, Node.TYPE_LAZY);
        Interpreter interpreter = Interpreter.mySelf();
        StaticHeap global = interpreter.getGLOBAL();
        boolean oldCanLoop = interpreter.isCanLoop();
        boolean oldInLoop = interpreter.isInLoop();
        interpreter.setCanLoop(true);
        interpreter.setInLoop(true);

        //
        int href = global.size();
        int slock = global.getOffset();
        //int tlock = global.getTailStack().getLock();


        // FERMETURE NECESSAIRE...
        //System.out.println("FOREVER: push...");
        global.push();
        Heap local=global.current();
       
        /*
         * Correction du 10 mai 2011:
         * =========================
         *    Les boucles du type do{...} s'arrête dès qu'un résultat est retourné. Cela ne signifie
         *    bien entendu pas que la condition qui permet l'itération n'est pas vérifiée. Toutefois,
         *    comme les boucle du type do{...} ne peuvent retourner qu'un seul résultat, il est inutile
         *    de relancer l'itération suivante ddès qu'un résultat est fourni. Ainsi, pour permettre
         *    de continuer la boucle, il est possible de placer le résultat dans une variable et non de
         *    la retourner directement comme résultat.
         *   
         */
        while (xnode==null && interpreter.isCanIterate()) {
            _clear_closure_(local);
            xnode = enode.exec(true);
        }
        global.pull();


        //global.getTailStack().setLock(tlock); // restore la tail recursive Stack...
        if (global.size() != href) {
            global.setOffset(slock);
            global.setSize(href); // restaurer le heap à la bonne taille
        }
        //
        interpreter.consumeBreakCode_onLoop();
        interpreter.setCanLoop(oldCanLoop);
        interpreter.setInLoop(oldInLoop);
        return xnode;
    }


}
TOP

Related Classes of abstrasy.pcfx.PCFx_do

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.