Package kiss.lang.expression

Source Code of kiss.lang.expression.Do

package kiss.lang.expression;

import java.util.Arrays;

import kiss.lang.Environment;
import kiss.lang.Expression;
import kiss.lang.Type;
import kiss.lang.impl.KissException;
import kiss.lang.type.Nothing;
import clojure.lang.IPersistentMap;
import clojure.lang.IPersistentSet;

/**
* A Kiss "do" expression.
*
* All subexpressions are evaluated in sequence, and the result is the result of the final
* subexpression.
*
* @author Mike
*
*/
public class Do extends kiss.lang.Expression {
  private final Expression[] exps;
  private final int length;
 
  private Do(Expression[] exps) {
    this.exps=exps;
    length=exps.length;
  }
 
  public static Do create(Expression... exps) {
    return new Do(exps);
  }
 
  @Override
  public Type getType() {
    if (length==0) return Nothing.INSTANCE;
    return exps[length-1].getType();
  }
 
  @Override
  public Expression optimise() {
    Expression[] es=new Expression[length];
    int j=0;
    boolean found=false;
    for (int i=0; i<length; i++) {
      Expression old=exps[i];
      Expression x=old.optimise();
      if (x!=old) found=true;
      // we can eliminate pure expressions in non-ending position
      if ((i==(length-1))||(!x.isPure())) {
        es[j++]=x;
      }
    }
    if ((!found)&&(j==length)) return this;
    if (j==1) return es[0];
    return create(Arrays.copyOf(es, j));
  }
 
  @Override
  public boolean isPure() {
    for (Expression e:exps) {
      if (!e.isPure()) return false;
    }
    return true;
  }

  @Override
  public Expression specialise(Type type) {
    // specialise based on the last expression in the do block, since this defines the return value
    if (length==0) return null;
    Expression end=exps[length-1];
    Expression send=end.specialise(type);
    if (send==null) return null;
    if (send==end) return this;
    Expression[] nexps=exps.clone();
    nexps[length-1]=send;
    return create(nexps);
  }
 
  @Override
  public Expression substitute(IPersistentMap bindings) {
    int i=0;
    Expression nx=null;
    for (;i<length; i++) {
      Expression x=exps[i];
      nx=x.substitute(bindings);
      if (nx==null) return null;
      if (nx!=x) break;
    }
    if (i==length) return this; // no changes
    Expression[] nexps=exps.clone();
    nexps[i++]=nx;
    for (;i<length; i++) {
      Expression x=exps[i];
      nx=x.substitute(bindings);
      if (nx==null) return null;
      nexps[i]=nx;
    }
    return create(nexps);
  }

  @Override
  public Environment compute(Environment e, IPersistentMap bindings) {
    for (int i=0; i<length; i++) {
      e=exps[i].compute(e,bindings);
      if (e.isExiting()) return e;
    }
    return e;
  }

  @Override
  public IPersistentSet accumulateFreeSymbols(IPersistentSet s) {
    for (int i=0; i<length; i++) {
      s=exps[i].accumulateFreeSymbols(s);
    }
    return s;
  }
 
  @Override
  public void validate() {
    if (length!=exps.length) throw new KissException("Mismatched length!");
  }


}
TOP

Related Classes of kiss.lang.expression.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.