Package kiss.lang.expression

Source Code of kiss.lang.expression.If

package kiss.lang.expression;

import clojure.lang.IPersistentMap;
import clojure.lang.IPersistentSet;
import kiss.lang.Environment;
import kiss.lang.Expression;
import kiss.lang.Type;
import kiss.lang.impl.KissUtils;

/**
* Expression for a standard "if" conditional
*
* @author Mike
*/
public class If extends Expression {
  private final Type type;
  private final Expression cond;
  private final Expression doThen;
  private final Expression doElse;
 
  private If(Expression cond, Expression doThen, Expression doElse) {
    this.cond=cond;
    this.doThen=doThen;
    this.doElse=doElse;
    this.type=doThen.getType().union(doElse.getType());
  }
 
  public static Expression create(Expression cond,Expression doThen, Expression doElse) {
    return new If(cond,doThen,doElse);
  }
 
  public Expression update(Expression cond,Expression doThen, Expression doElse) {
    if (cond.isConstant()) {
      return (KissUtils.truthy(cond.eval()))?doThen:doElse;
    }
    if (cond.isPure()) {
      // we can optimise away the test only if cond is pure (i.e. no side effects)
      Type t=cond.getType();
      if (t.cannotBeFalsey()) return doThen;
      if (t.cannotBeTruthy()) return doElse;
    }
   
    if ((cond==this.cond)&&(doThen==this.doThen)&&(doElse==this.doElse)) return this;

    return new If(cond,doThen,doElse);
  }
 
  @Override
  public Expression optimise() {
    Expression cond=this.cond.optimise();
    Expression doThen=this.doThen.optimise();
    Expression doElse=this.doElse.optimise();
    return update(cond,doThen,doElse);
  }
 
  @Override
  public boolean isPure() {
    return cond.isPure()&&doThen.isPure()&&doElse.isPure();
  }

  @Override
  public Type getType() {
    return type;
  }

  @Override
  public Expression specialise(Type type) {
    Expression newThen=doThen.specialise(type);
    Expression newElse=doElse.specialise(type);
    if ((newThen==null)&&(newElse==null)) return null;
    return update(cond,newThen,newElse);
  }
 
  @Override
  public Expression substitute(IPersistentMap bindings) {
    Expression ncond=cond.substitute(bindings);
    if (ncond==null) return null;
    Expression nthen=doThen.substitute(bindings);
    if (nthen==null) return null;
    Expression nelse=doElse.substitute(bindings);
    if (nelse==null) return null;
   
    return update(ncond,nthen,nelse);
  }

  @Override
  public Environment compute(Environment d, IPersistentMap bindings) {
    d=cond.compute(d, bindings);
    if (d.isExiting()) return d;
    if (KissUtils.truthy(d.getResult())) {
      return doThen.compute(d, bindings);
    } else {
      return doElse.compute(d, bindings);
    }
  }
 
  @Override
  public IPersistentSet accumulateFreeSymbols(IPersistentSet s) {
    s=cond.accumulateFreeSymbols(s);
    s=doThen.accumulateFreeSymbols(s);
    s=doElse.accumulateFreeSymbols(s);
    return s;
  }

  @Override
  public void validate() {
    // OK?
  }

}
TOP

Related Classes of kiss.lang.expression.If

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.