Package erjang.m.ets

Source Code of erjang.m.ets.EPattern$NilPattern

/**
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2009 by Trifork
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

package erjang.m.ets;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Pattern;

import com.trifork.clj_ds.ISeq;

import erjang.EAtom;
import erjang.EBitString;
import erjang.ECons;
import erjang.EFun;
import erjang.EList;
import erjang.ENumber;
import erjang.EObject;
import erjang.EPID;
import erjang.EPort;
import erjang.ERT;
import erjang.ERef;
import erjang.ESeq;
import erjang.ETuple;

/**
*
*/
public class EPattern {

  ETermPattern matcher;
  private final EObject spec;
  private Integer[] out_vars;
  private final int keyidx;

  @Override
  public String toString() {
    return "#Pattern<keyidx=" + keyidx + ";" + spec.toString() + ">";
  }

  /**
   * @param spec
   */
  public EPattern(int keyidx, EObject spec) {
    this.keyidx = keyidx;
    this.spec = spec;
    SortedSet<Integer> out = new TreeSet<Integer>();

    matcher = spec.compileMatch(out);

    this.out_vars = out.toArray(new Integer[out.size()]);
  }

  ESeq match_members(ESeq out, Collection<ETuple> in) {

    for (EObject elm : in) {
      EMatchContext res = new EMatchContext(out_vars, elm);
      if (elm.match(matcher, res)) {
        out = out.cons(elm);
      }
    }

    return out;
  }

  ESeq match(ESeq out, Map<EObject, ETuple> in) {

    for (ETuple elm : in.values()) {
      ETuple val = elm.testTuple();
      EMatchContext res = new EMatchContext(out_vars, val);
      if (matcher.match(val, res)) {
        out = out.cons(res.makeList());
      }
    }

    return out;
  }

  /** return list of matching members */
  ESeq match_members(ESeq out, Map<EObject, ETuple> in) {

    for (ETuple elm : in.values()) {
      EMatchContext res = new EMatchContext(out_vars, elm);
      if (matcher.match(elm, res)) {
        out = out.cons(elm);
      }
    }

    return out;
  }

  /** return list of matching members */
  ESeq match_members(ESeq out, ISeq in) {

    while (in != null) {
      ETuple elm = (ETuple) in.first();
      if (elm == null)
        break;

      EMatchContext res = new EMatchContext(out_vars, elm);
      if (matcher.match(elm, res)) {
        out = out.cons(elm);
      }

      in = in.next();
    }

    return out;
  }

  /** return list of matching members' vars */
  ESeq match_vars(ESeq out, ISeq in) {

    while (in != null) {
      ETuple elm = (ETuple) in.first();
      if (elm == null)
        break;

      EMatchContext res = new EMatchContext(out_vars, elm);
      if (matcher.match(elm, res)) {
        out = out.cons(res.makeList());
      }

      in = in.next();
    }

    return out;
  }

  public static EPattern compile(int keyidx, ETuple spec) {
    return new EPattern(keyidx, spec);
  }

  /** matcher for '_' */
  static class AnyPattern extends ETermPattern {
    public boolean match(ETuple t, EMatchContext r) {
      return true;
    }

    public boolean match(ENumber n, EMatchContext r) {
      return true;
    }

    public boolean match(EAtom a, EMatchContext r) {
      return true;
    }

    public boolean match(ECons c, EMatchContext r) {
      return true;
    }

    public boolean match(EPID p, EMatchContext r) {
      return true;
    }

    public boolean match(EPort p, EMatchContext r) {
      return true;
    }

    public boolean match(EBitString bs, EMatchContext r) {
      return true;
    }

  }

  /** matcher for '$N' */
  static class VarPattern extends ETermPattern {
    private Integer name;
    private boolean free;

    /**
     * @param idx2
     * @param out
     */
    public VarPattern(int idx1, Set<Integer> out) {
      this.name = idx1;
      if (this.free = !out.contains(this.name)) {
        out.add(this.name);
      }
    }

    public boolean match(ETuple t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(ENumber t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(EAtom t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(EFun fu, EMatchContext r) {
      if (free) {
        r.vars.put(name, fu);
        return true;
      } else {
        return fu.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(ERef fu, EMatchContext r) {
      if (free) {
        r.vars.put(name, fu);
        return true;
      } else {
        return fu.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(ECons t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(EPID t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(EPort t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }

    public boolean match(EBitString t, EMatchContext r) {
      if (free) {
        r.vars.put(name, t);
        return true;
      } else {
        return t.equalsExactly(r.vars.get(name));
      }
    }
  }

  static class TuplePattern extends ETermPattern {
    int arity;
    ETermPattern[] elems;

    /**
     * @param tup
     * @param out
     */
    public TuplePattern(ETuple tup, Set<Integer> out) {
      arity = tup.arity();
      elems = new ETermPattern[arity];
      for (int idx1 = 1; idx1 <= arity; idx1++) {
        elems[idx1 - 1] = tup.elm(idx1).compileMatch(out);
      }
    }

    public boolean match(EObject elm, EMatchContext res) {
      ETuple tup;
      if ((tup = elm.testTuple()) == null)
        return false;
      return match(tup, res);
    }

    public boolean match(ETuple t, EMatchContext r) {
      if (t.arity() != arity)
        return false;
      for (int idx1 = 1; idx1 < elems.length + 1; idx1++) {
        if (!t.elm(idx1).match(elems[idx1 - 1], r))
          return false;
      }
      return true;
    }
  }

  static class NilPattern extends ETermPattern {
    @Override
    public boolean match(ECons c, EMatchContext r) {
      return c.isNil();
    }
  }

  static class ConsPattern extends ETermPattern {

    ETermPattern head, tail;

    /**
     * @param cons
     * @param out
     */
    public ConsPattern(ECons cons, Set<Integer> out) {
      head = cons.head().compileMatch(out);
      tail = cons.tail().compileMatch(out);
    }

    public boolean match(ECons c, EMatchContext r) {
      return (!c.isNil()) && c.head().match(head, r) && c.tail().match(tail, r);
    }
  }

  /** matcher for all the non-recursive types */
  static class ValuePattern extends ETermPattern {
    final EObject value;

    /**
     * @param epid
     */
    public ValuePattern(EObject val) {
      this.value = val;
    }

    public boolean match(EPID pid, EMatchContext r) {
      return pid.equalsExactly(value);
    }

    public boolean match(ERef ref, EMatchContext r) {
      return ref.equalsExactly(value);
    }

    public boolean match(EPort port, EMatchContext r) {
      return port.equalsExactly(value);
    }

    public boolean match(EAtom port, EMatchContext r) {
      return port.equalsExactly(value);
    }

    public boolean match(EFun fu, EMatchContext r) {
      return fu.equalsExactly(value);
    }

    public boolean match(EBitString port, EMatchContext r) {
      return port.equalsExactly(value);
    }

    public boolean match(ENumber num, EMatchContext r) {
      return num.equalsExactly(value);
    }

    public boolean match(ETuple t, EMatchContext r) {
      return t.equalsExactly(value);
    }

    @Override
    public boolean match(ECons c, EMatchContext r) {
      return c.equalsExactly(value);
    }

  }

  /**
   * @param eTuple
   * @param out
   * @return
   */
  public static ETermPattern compilePattern(ETuple tup, Set<Integer> out) {
    TuplePattern tp = new TuplePattern(tup, out);
    for (int i = 0; i < tp.elems.length; i++) {
      if (!(tp.elems[i] instanceof ValuePattern)) {
        return tp;
      }
    }
    return new ValuePattern(tup);
  }

  /** generic compare-equals matcher */
  public static ETermPattern compilePattern(EObject epid, Set<Integer> out) {
    return new ValuePattern(epid);
  }

  /**
   * @param eCons
   * @param out
   * @return
   */
  public static ETermPattern compilePattern(ECons cons, Set<Integer> out) {
    if (cons.isNil()) {
      return new NilPattern();
    } else {
      return new ConsPattern(cons, out);
    }
  }

  static Pattern VAR = Pattern.compile("^\\$[0-9]+$");
  static EAtom am_ANY = EAtom.intern("_");

  /**
   * @param eAtom
   * @param out
   * @return
   */
  public static ETermPattern compilePattern(EAtom am, Set<Integer> out) {
    String name = am.getName();

    if (VAR.matcher(name).matches()) {
      int idx1 = Integer.parseInt(name.substring(1));
      return new VarPattern(idx1, out);
    } else if (am == am_ANY) {
      return new AnyPattern();
    } else {
      return new ValuePattern(am);
    }
  }

  /**
   * @param keypos1
   * @return
   */
  public EObject getKey(int keypos1) {
    if (matcher instanceof TuplePattern) {
      TuplePattern tm = (TuplePattern) matcher;
      if (keypos1 < 1 || keypos1 > tm.elems.length) {
        return null;
      }
      ETermPattern m = tm.elems[keypos1 - 1];
      if (m instanceof ValuePattern) {
        ValuePattern vm = (ValuePattern) m;
        return vm.value;
      }
    } else if (matcher instanceof ValuePattern) {
      ValuePattern vp = (ValuePattern) matcher;
      if (vp.value instanceof ETuple) {
        ETuple et = (ETuple) vp.value;
        if (keypos1 < 1 || keypos1 > et.arity())
          return null;
        return et.elm(keypos1);
      }
    }
    return null;
  }

  /**
   * @param res
   * @param candidate
   * @return
   */
  ESeq match(ESeq out, ETuple val) {
    EMatchContext res = new EMatchContext(out_vars, val);

    if (matcher.match(val, res)) {
      out = out.cons(res.makeList());
    }

    return out;
  }

  ESeq match_members(ESeq out, ETuple val) {
    EMatchContext res = new EMatchContext(out_vars, val);

    if (matcher.match(val, res)) {
      out = out.cons(val);
    }

    return out;
  }

  boolean match(ETuple val) {
    EMatchContext res = new EMatchContext(out_vars, val);
    return matcher.match(val, res);
  }

}
TOP

Related Classes of erjang.m.ets.EPattern$NilPattern

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.