Package kiss.lang

Source Code of kiss.lang.Analyser

package kiss.lang;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import kiss.lang.expression.Application;
import kiss.lang.expression.ClojureLookup;
import kiss.lang.expression.Constant;
import kiss.lang.expression.Def;
import kiss.lang.expression.Do;
import kiss.lang.expression.If;
import kiss.lang.expression.InstanceOf;
import kiss.lang.expression.Lambda;
import kiss.lang.expression.Let;
import kiss.lang.expression.Lookup;
import kiss.lang.expression.Loop;
import kiss.lang.expression.Recur;
import kiss.lang.expression.Return;
import kiss.lang.expression.Vector;
import kiss.lang.impl.KissException;
import kiss.lang.impl.KissUtils;
import kiss.lang.type.Anything;
import kiss.lang.type.Intersection;
import kiss.lang.type.JavaType;
import kiss.lang.type.Nothing;
import kiss.lang.type.Null;
import kiss.lang.type.Union;
import clojure.lang.IFn;
import clojure.lang.IPersistentMap;
import clojure.lang.IPersistentVector;
import clojure.lang.ISeq;
import clojure.lang.PersistentHashMap;
import clojure.lang.RT;
import clojure.lang.Symbol;

/**
* Kiss language analyser
*
* Design intent:
* - Converts Clojure forms to Kiss ASTs
*
* @author Mike
*/
public class Analyser {

  /**
   * Converts a Kiss form into an Expression
   *
   * @param form
   * @return
   */
  public static Expression analyse(Object form) {
    if (form instanceof Symbol) return analyseSymbol((Symbol)form);
    if (form instanceof ISeq) return analyseSeq((ISeq)form);
    if (form instanceof IPersistentVector) return analyseVector((IPersistentVector)form);
    if (form instanceof IPersistentMap) return analyseMap((IPersistentMap)form);
    return Constant.create(form);
  }
 
  @SuppressWarnings("unchecked")
  public static Type analyseType(Object form) {
    if (form instanceof Symbol) {
      return analyseTypeSymbol((Symbol)form);
    }
    if (form instanceof Class) {
      return JavaType.create((Class<Object>) form);
    }
    if (form instanceof ISeq) {
      return analyseTypeSeq((ISeq)form);
    }
    throw new KissException("Unrecognised type form: "+form);
  }
 
  private static Type analyseTypeSymbol(Symbol sym) {
    if (sym.equals(Symbols.ANY)) return Anything.INSTANCE;
    if (sym.equals(Symbols.NOTHING)) return Nothing.INSTANCE;
    if (sym.equals(Symbols.NIL)) return Null.INSTANCE;
    if (sym.equals(Symbols.TYPE)) return JavaType.KISS_TYPE;
    if (sym.equals(Symbols.SYMBOL_TYPE)) return JavaType.SYMBOL;
    if (sym.equals(Symbols.KEYWORD_TYPE)) return JavaType.KEYWORD;
   
    if (sym.getNamespace()==null) {
      String name=sym.getName();
      if (!name.contains(".")) name="java.lang."+name;
      Class<?> c=RT.classForName(name);
      if (c!=null) return JavaType.create(c);
    }
    throw new KissException("Unrecognised type symbol: "+sym);
  }

  private static Type analyseTypeSeq(ISeq s) {
    List<Object> al=KissUtils.asList(s);
    Symbol sym=(Symbol) al.get(0);
    if (sym.equals(Symbols.U)) {
      Type[] types=analyseSequenceOfTypes(al,1,al.size()-1);
      return Union.create(types);
    } else if (sym.equals(Symbols.I)) {
      Type[] types=analyseSequenceOfTypes(al,1,al.size()-1);
      return Intersection.create(types);
    }
    throw new KissException("Unrecognised type form: "+s);   
  }

  private static Type[] analyseSequenceOfTypes(List<Object> al, int start, int length) {
    Type[] types=new Type[length];
    for (int i=0; i<length; i++) {
      types[i]=analyseType(al.get(start+i));
    }
    return types;
  }

  public static Expression analyseSymbol(Symbol sym) {
    if (sym.equals(Symbols.NIL)) return Constant.NULL;
    if (sym.equals(Symbols.TRUE)) return Constant.TRUE;
    if (sym.equals(Symbols.FALSE)) return Constant.FALSE;
    if (sym.getNamespace()!=null) return ClojureLookup.create(sym);
    return Lookup.create(sym);
  }

  private static Expression analyseVector(IPersistentVector form) {
    ArrayList<Expression> al=new ArrayList<Expression>();
    int n=form.count();
    for (int i=0; i<n; i++) {
      al.add(analyse(form.nth(i)));
    }
    return Vector.create(al);
  }
 
  @SuppressWarnings({ "rawtypes", "unchecked" })
  private static Expression analyseMap(IPersistentMap form) {
    HashMap<Expression,Expression> hm=new HashMap<Expression,Expression>();
    Iterator<Map.Entry> it=form.iterator();
    while (it.hasNext()) {
      Map.Entry e=it.next();
      hm.put(analyse(e.getKey()), analyse(e.getValue()));
    }
    return kiss.lang.expression.Map.create(hm);
  }

 
  private static Expression analyseSeq(ISeq form) {
    int n=form.count();
    if (n==0) return Constant.create(form);
    Object first=form.first();
   
    if (first instanceof Symbol) {
      Symbol s=(Symbol)first;
      if (s.equals(Symbols.LET)) {
        IPersistentVector v=KissUtils.expectVector(RT.second(form));
        int vc=v.count();
        if ((vc&1)!=0) throw new KissException("let requires an even number of binding forms");
       
        // start with expression body
        Expression e = analyse(RT.nth(form, 2));
       
        for (int i=vc-2; i>=0; i-=2) {
          Symbol sym=KissUtils.expectSymbol(v.nth(i));
          Expression exp=analyse(v.nth(i+1));
          e= Let.create(sym, exp, e);
        }
        return e;
      }
     
      if (s.equals(Symbols.LOOP)) {
        IPersistentVector v=KissUtils.expectVector(RT.second(form));
        int vc=v.count();
        if ((vc&1)!=0) throw new KissException("let requires an even number of binding forms");
       
        Symbol[] syms=new Symbol[vc/2];
        Expression[] initials=new Expression[vc/2];
       
        for (int i=0; i<vc; i+=2) {
          syms[i]=KissUtils.expectSymbol(v.nth(i));
          initials[i+i]=analyse(v.nth(i+1));
        }
        Expression body = analyse(RT.nth(form, 2));
        return Loop.create(syms, initials, body);
      }
     
      if (s.equals(Symbols.RECUR)) {
        int vc=n-1;
        Expression[] values=new Expression[vc];
       
        for (int i=0; i<vc; i++) {
          values[i]=analyse(RT.nth(form,(i+1)));
        }
        return Recur.create(values);
      }
     
      if (s.equals(Symbols.RETURN)) {
        Expression value=analyse(RT.nth(form,1));
        return Return.create(value);
      }
     
      if (s.equals(Symbols.IF)) {
        switch (n) {
        case 4:
          return If.create(analyse(RT.nth(form, 1)), analyse(RT.nth(form, 2)), analyse(RT.nth(form, 3)));
        case 3:
          return If.create(analyse(RT.nth(form, 1)), analyse(RT.nth(form, 2)),Constant.NULL);
        default:
          throw new KissException("Wrong number of forms in if expression: "+n);
        }   
      }
     
      if (s.equals(Symbols.INSTANCE)) {
        switch (n) {
        case 3:
          return InstanceOf.create(analyseType(RT.nth(form, 1)), analyse(RT.nth(form, 2)));
        default:
          throw new KissException("Wrong number of forms in instance? expression: "+n);
        }   
      }
     
      if (s.equals(Symbols.DEF)) {
        if (n!=3) throw new KissException("Wrong number of forms in def expression: "+n);
        Symbol sym=(Symbol)RT.nth(form,1);
        return Def.create(sym,analyse(RT.nth(form, 2)));   
      }

      if (s.equals(Symbols.DO)) {
        Expression[] exps=new Expression[n-1];
        for (int i=1; i<n; i++) {
          exps[i-1]=analyse(RT.nth(form, i));
        }
        return Do.create(exps);
      }
     
      if (s.equals(Symbols.FN)) {
        IPersistentVector v=KissUtils.expectVector(RT.second(form));
        int arity=v.count();
        Symbol[] syms=new Symbol[arity];
        Type[] types=new Type[arity];
        for (int i=0; i<arity; i++) {
          Symbol paramSym=(Symbol)v.nth(i);
          syms[i]=paramSym;
          Type paramType=Type.resolveTag(s);
          types[i]=paramType;
        }
        Expression body=analyse(RT.nth(form, 2));
       
        return Lambda.create(body,syms,types);
      }
    }
   
    Expression fn=analyse(first);
    if (KissUtils.isMacro(fn)) {
      // TODO: macro expend with expansion passing?
      IFn macroFn=(IFn) fn.eval(Environment.EMPTY);
      Object expandedForm=macroFn.applyTo(RT.cons(form,RT.cons(PersistentHashMap.EMPTY, form.next())));
      return analyse(expandedForm);
    }
   
    ISeq paramSeq=RT.next(form);
    int paramCount=RT.count(paramSeq);
    Expression[] params=new Expression[paramCount];
    int i=0;
    for (ISeq s=RT.seq(paramSeq); s!=null; s=s.next()) {
      params[i++]=analyse(s.first());
    }
   
    return Application.create(fn,params);
   
    // throw new KissException("Unexpected form: "+form);
  }
}
TOP

Related Classes of kiss.lang.Analyser

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.