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

tyRuBa.engine.RBExpression Maven / Gradle / Ivy

package tyRuBa.engine;

import java.util.Collection;

import junit.framework.Assert;

import tyRuBa.engine.compilation.CompilationContext;
import tyRuBa.engine.compilation.Compiled;
import tyRuBa.engine.visitor.CollectFreeVarsVisitor;
import tyRuBa.engine.visitor.CollectTemplateVarsVisitor;
import tyRuBa.engine.visitor.CollectVarsVisitor;
import tyRuBa.engine.visitor.ExpressionVisitor;
import tyRuBa.engine.visitor.SubstituteVisitor;
import tyRuBa.modes.ErrorMode;
import tyRuBa.modes.Factory;
import tyRuBa.modes.Mode;
import tyRuBa.modes.ModeCheckContext;
import tyRuBa.modes.PredInfoProvider;
import tyRuBa.modes.Type;
import tyRuBa.modes.TypeConstructor;
import tyRuBa.modes.TypeEnv;
import tyRuBa.modes.TypeModeError;
import tyRuBa.parser.ParseException;
import tyRuBa.tdbc.PreparedQuery;

public abstract class RBExpression implements Cloneable {

    private Mode mode = null;
    private ModeCheckContext newContext = null;
    
	abstract public Compiled compile(CompilationContext c);

	PreparedQuery prepareForRunning(QueryEngine engine, boolean typeCheck)
		throws TypeModeError, ParseException {
		engine.frontend().autoUpdateBuckets();
		RBExpression converted = convertToNormalForm();
		TypeEnv resultEnv = null;
		if (typeCheck) 
			resultEnv = converted.typecheck(engine.rulebase(), Factory.makeTypeEnv());
		else
			resultEnv = converted.fakecheck(engine.rulebase(), Factory.makeTypeEnv());
		RBExpression result =
			converted.convertToMode(Factory.makeModeCheckContext(engine.rulebase()));
		if (result.getMode() instanceof ErrorMode) {
			throw new TypeModeError(
				this + " cannot be converted to any declared mode\n" +
					"   " + result.getMode());
		} else if (!RuleBase.silent) {
			if (typeCheck)
				System.err.println("inferred types: " + resultEnv);
			System.err.println("converted to Mode: " + result);
		}
		//Compiled compExp = result.getExp().compile(new CompilationContext());
		return new PreparedQuery(engine, result, resultEnv);
	}

	/** 
	 * A quick hack used to execute queries without type checking. 
	 * This performs similar to the typecheck method but instead of checking
	 * types it merely retrieves the variables from the query and associates
	 * the type Object with them.
	 */
	private TypeEnv fakecheck(ModedRuleBaseIndex index, TypeEnv env) {
		Type object = TypeConstructor.theAny.apply(Factory.makeTupleType(), false);
		Collection vars = getTemplateVariables();
		for (Object var : vars) {
			env.put(var, object);
		}
		return env;
	}

	/**
	 * Returns all the template variables (input for prepared queries)
	 * found in this expression.
	 */
	private Collection getTemplateVariables() {
		CollectTemplateVarsVisitor visitor = new CollectTemplateVarsVisitor();
		this.accept(visitor);
		Collection vars = visitor.getVars();
		return vars;
	}

	/**
	 * Returns a Collection of variables bound by this query expression.
	 */
	public final Collection getVariables() {
		CollectVarsVisitor visitor = new CollectVarsVisitor();
		this.accept(visitor);
		Collection vars = visitor.getVars();
		vars.remove(RBIgnoredVariable.the);
		return vars;
	}
	
	/**
	 * Returns a Cpllection of variables bound by this query expression that do
	 * not become bound in the context.
	 */
	public final Collection getFreeVariables(ModeCheckContext context) {
		CollectFreeVarsVisitor visitor = new CollectFreeVarsVisitor(context);
		this.accept(visitor);
		return visitor.getVars();
	}
	
	public abstract TypeEnv typecheck(PredInfoProvider predinfo, TypeEnv startEnv)
	throws TypeModeError;

	public final RBExpression convertToMode(ModeCheckContext context)
	throws TypeModeError {
		return convertToMode(context, true);
	}

	public abstract RBExpression convertToMode(ModeCheckContext context,
	boolean rearrange) throws TypeModeError;

	
	public RBExpression convertToNormalForm() {
		return convertToNormalForm(false);
	}
	
	public RBExpression convertToNormalForm(boolean negate) {
		RBExpression result;
		if (negate) {
			result = new RBNotFilter(this);
		} else {
			result = this;
		}
		return result;
	}
	
	public RBExpression crossMultiply(RBExpression other) {
		if (other instanceof RBCompoundExpression)
			return other.crossMultiply(this);
		return FrontEnd.makeAnd(this, other);
	}

	public abstract Object accept(ExpressionVisitor v);
	
	public RBExpression substitute(Frame frame) {
		SubstituteVisitor visitor = new SubstituteVisitor(frame);
		return (RBExpression) accept(visitor);
	}

	public RBExpression addExistsQuantifier(RBVariable[] newVars, boolean negate) {
		RBExistsQuantifier exists = new RBExistsQuantifier(newVars, this);
		if (negate) {
			return new RBNotFilter(exists);
		} else {
			return exists;
		}
	}

    public RBExpression makeModed(Mode mode, ModeCheckContext context) {
        try {
            RBExpression clone = (RBExpression) this.clone();
            clone.setMode(mode,context);
            return clone;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            throw new Error("Should not happen");
        }     
    }

    /**
     * This method should only be called while initializing a Moded expression.
     */
    private void setMode(Mode mode, ModeCheckContext context) {
 //       Assert.assertNull(this.mode);
        this.mode = mode;
        this.newContext = context;
    }

    /** Return true if this moded expression returns less result than other*/
    public boolean isBetterThan(RBExpression other) {
        return getMode().isBetterThan(other.getMode());
    }

    protected Mode getMode() {
        return mode;
    }

    public ModeCheckContext getNewContext() {
        Assert.assertNotNull(newContext);
        return newContext;
    }

//    public String toString() {
//        return "ModedExpression: " + getExp() + "\n with mode: " + getMode() 
//            + "\n and context: " + getNewContext();
//    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy