All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jclarion.clarion.runtime.expr.CExpr Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2010, by Andrew Barnham
 *
 * The contents of this file are subject to
 * GNU Lesser General Public License (LGPL), v.3
 * http://www.gnu.org/licenses/lgpl.txt
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 */
package org.jclarion.clarion.runtime.expr;

import java.util.Iterator;
import java.util.Stack;

import org.jclarion.clarion.ClarionObject;

public abstract class CExpr 
{
    /**
     *  Work out expression type
     *  
     * @return
     */
    public abstract CExprType getType();

    /**
     *  Force expr type to a new cast
     *  
     * @return
     */
    public abstract void cast(CExprType type);
    
    /**
     * Return whether or not expression type is fixed. i.e. cannot be easily recast
     */
    public abstract boolean isRecastableType();
    
    /**
     * Generate result
     * @return
     */
    public abstract ClarionObject eval();
    
    /**
     * Return order of precendence. 
     * 
     * Low number = low order of precedence (i.e. bool etc)
     * 
     * Hi number = high order of precendence (i.e. * % / etc ). Highest is constants
     * 
     * When rebuilding expressions (i.e. SQL) you need to paran anything whose
     * precendence is lower then yourself i.e.
     * 
     * Sum(Prod,Prod) = 2*3 + 6*3 
     * 
     * Prod(Sum,Sum)  = (2+3) * (6+3)
     */
    public abstract int precendence();
    
    public abstract Iterator directChildren();
    
    /**
     * Generate SQL capable string.
     * 
     *  if strict is false (not strict mode) then it will generate
     *  expression faithfully without consideration as to whether or
     *  not it will yield legal SQL
     *  
     *  If strict mode is set - then only faithful SQL will be yielded
     *  return result in this case will indicate whether or not 
     *  this call of generateString yielded SQL. 
     *  
     *  If a method returns false it must preserve StringBuilder as is 
     *  
     *  e.g. Pow() will always return false.
     *  e.g. BoolExpr will return false if there are any 'OR' components which are
     *  not strict SQL
     */
    public abstract boolean generateString(StringBuilder out,boolean strict);
    
    public Iterator iterator()
    {
        return new JoinIterator(new OneIterator(this),new DeepIterator(this));
    }

    protected static class GenericOp
    {
        public CExpr right;
    }

    public static class DeepIterator implements Iterator
    {
        private Stack> stack;
        private Iterator current;
        
        public DeepIterator(CExpr base)
        {
            stack=new Stack>();
            current=base.directChildren();
        }

        @Override
        public boolean hasNext() {
            if (current==null) return false;
            while (!current.hasNext()) {
                if (stack.isEmpty()) {
                    current=null;
                    return false;
                }
                current=stack.pop();
            }
            
            return true;
        }

        @Override
        public CExpr next() {
            if (!hasNext()) return null;
            
            CExpr next = current.next();
            if (current.hasNext()) { 
                // only push it if it has something more to offer
                stack.push(current); 
            }
            current=next.directChildren();
            if (current==null) return null;
            
            return next;
        }

        @Override
        public void remove() {
        }
    }
    
    public static class ZeroIterator implements Iterator
    {
        @Override
        public boolean hasNext() {
            return false;
        }

        @Override
        public CExpr next() {
            return null;
        }

        @Override
        public void remove() {
        }
    }
    
    public static class OneIterator implements Iterator
    {
        private CExpr e;
        
        public OneIterator(CExpr e)
        {
            this.e=e;
        }
        
        @Override
        public boolean hasNext() {
            return (e!=null);
        }

        @Override
        public CExpr next() {
            CExpr r =e;
            e=null;
            return r;
        }

        @Override
        public void remove() {
        }
    }

    public static class TwoIterator implements Iterator
    {
        private CExpr e1;
        private CExpr e2;
        
        public TwoIterator(CExpr e1,CExpr e2)
        {
            this.e1=e1;
            this.e2=e2;
        }
        
        @Override
        public boolean hasNext() {
            return (e1!=null || e2!=null);
        }

        @Override
        public CExpr next() {
            CExpr r =null;
            if (e1!=null) {
                r=e1;
                e1=null;
            } else if (e2!=null) {
                r=e2;
                e2=null;
            }
            return r;
        }

        @Override
        public void remove() {
        }
    }

    public static class OpIterable implements Iterable
    {
        private Iterable op;
        
        public OpIterable(Iterable op) {
            this.op=op;
        }
        
        @Override
        public Iterator iterator() {
            return new OpIterator(op.iterator());
        }
        
    }
    
    public static class OpIterator implements Iterator
    {
        private Iterator op;
        
        public OpIterator(Iterator op)
        {
            this.op=op;
        }

        @Override
        public boolean hasNext() {
            return op.hasNext();
        }

        @Override
        public CExpr next() {
            GenericOp o = op.next();
            if (o==null) return null;
            return o.right;
        }

        @Override
        public void remove() {
        }
    }
    
    public static class JoinIterator implements Iterator
    {
        private Iterator e1;
        private Iterator e2;
        
        public JoinIterator(Iterator e1,Iterator e2)
        {
            this.e1=e1;
            this.e2=e2;
        }

        public JoinIterator(CExpr e1,Iterable e2)
        {
            this.e1=new OneIterator(e1);
            this.e2=e2.iterator();;
        }

        public static JoinIterator generic(CExpr e1,Iterable e2) 
        {
            return new JoinIterator(new OneIterator(e1),new OpIterator(e2.iterator()));
        }

        @Override
        public boolean hasNext() {
            return (e1.hasNext() || e2.hasNext());
        }

        @Override
        public CExpr next() {
            if (e1.hasNext()) return e1.next();
            if (e2.hasNext()) return e2.next();
            return null;
        }

        @Override
        public void remove() {
        }
    }

    protected CExprType resolveCasts(Iterable in)
    {
        CExprType type=null;
        boolean   force=false;
        
        for ( CExpr scan : in ) {
            if (type==null || !force) {
                type=scan.getType();
                force=!scan.isRecastableType();
                continue;
            }
        }
        return type;
    }

    protected boolean isRecastableType(Iterable in)
    {
        for ( CExpr scan : in ) {
            if (!scan.isRecastableType()) return false; 
        }
        return true;
    }
    
    protected void cast(Iterable in,CExprType type)
    {
        for ( CExpr scan : in ) {
            scan.cast(type);
        }
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy