Esempio n. 1
0
  /*
   * We are positioned in the pattern at a list variable and match it with
   * the current subject starting at the current position.
   * On success, the cursors are advanced.
   * On failure, switch to backtracking (forward = false) mode.
   */
  private void matchBindingListVar(IMatchingResult child) {

    assert isListVar[patternCursor];

    int start = listVarStart[patternCursor];
    int length = listVarLength[patternCursor];

    //  int reducedLength = (length == 0) ? 0 : ((length < delta) ? 1 : Math.max(length - delta + 1,
    // 0));  // round to nearest unskipped element

    int reducedLength = (length <= 1) ? length : (length - (length - 1) % delta);

    if (debug) {
      System.err.println("length=" + length);
      System.err.println("reducedLength=" + reducedLength);
    }

    IList sublist = makeSubList(start, reducedLength);

    if (debug)
      System.err.println(
          "matchBindingListVar: init child #" + patternCursor + " (" + child + ") with " + sublist);
    // TODO : check if we can use a static type here!?
    child.initMatch(ResultFactory.makeResult(sublist.getType(), sublist, ctx));

    if (child.next()) {
      subjectCursor = start + length;
      if (debug) System.err.println("child matches, subjectCursor=" + subjectCursor);
      patternCursor += delta;
    } else {
      forward = false;
      listVarLength[patternCursor] = 0;
      patternCursor -= delta;
      if (debug) System.err.println("child fails, subjectCursor=" + subjectCursor);
    }
  }
Esempio n. 2
0
  @Override
  public void initMatch(Result<IValue> subject) {
    if (debug) {
      System.err.println("List: initMatch: subject=" + subject);
    }

    //    This is an experiment to add abstract list matching for concrete subjects
    //    if (subject.getType().isSubtypeOf(Factory.Tree)) {
    //      IConstructor tree = (IConstructor) subject.getValue();
    //      if (TreeAdapter.isList(tree)) {
    //        subject = ResultFactory.makeResult(Factory.Args, TreeAdapter.getArgs(tree), ctx);
    //        IConstructor rhs = TreeAdapter.getType(tree);
    //
    //        if (SymbolAdapter.isIterPlusSeps(rhs) || SymbolAdapter.isIterStarSeps(rhs)) {
    //          this.delta = SymbolAdapter.getSeparators(rhs).length() + 1;
    //        }
    //      }
    //      else {
    //        hasNext = false;
    //        return;
    //      }
    //    }

    super.initMatch(subject);

    if (!subject.getValue().getType().isList()) {
      hasNext = false;
      return;
    }
    listSubject = (IList) subject.getValue();
    listSubjectType = listSubject.getType();
    staticListSubjectType = subject.getType();
    staticListSubjectElementType =
        staticListSubjectType.isList() ? subject.getType().getElementType() : tf.valueType();

    subjectCursor = 0;
    patternCursor = 0;
    subjectSize = ((IList) subject.getValue()).length();
    reducedSubjectSize = (subjectSize + delta - 1) / delta;

    if (debug) {
      System.err.println("reducedPatternSize=" + reducedPatternSize);
      System.err.println("reducedSubjectSize=" + reducedSubjectSize);
    }

    isListVar = new boolean[patternSize];
    isBindingVar = new boolean[patternSize];
    varName = new String[patternSize];
    allVars = new HashSet<String>();
    listVarStart = new int[patternSize];
    listVarLength = new int[patternSize];
    listVarMinLength = new int[patternSize];
    listVarMaxLength = new int[patternSize];
    listVarOccurrences = new int[patternSize];

    int nListVar = 0;
    /*
     * Pass #1: determine the list variables
     */
    for (int i = 0; i < patternSize; i += delta) {
      IMatchingResult child = patternChildren.get(i);
      isListVar[i] = false;
      isBindingVar[i] = false;
      Environment env = ctx.getCurrentEnvt();

      if (child instanceof TypedMultiVariablePattern) {
        TypedMultiVariablePattern tmvVar = (TypedMultiVariablePattern) child;
        Type tmvType = tmvVar.getType(env, null);
        String name = tmvVar.getName();

        varName[i] = name;
        isListVar[i] = true;
        listVarOccurrences[i] = 1;
        ++nListVar;

        if (!tmvVar.isAnonymous() && allVars.contains(name)) {
          throw new RedeclaredVariable(name, getAST());
        } else if (tmvType.comparable(listSubject.getType().getElementType())
            || (tmvVar.bindingInstance() && tmvType.comparable(listSubject.getType()))) {
          tmvVar.convertToListType();
          if (!tmvVar.isAnonymous()) {
            allVars.add(name);
          }
          isBindingVar[i] = true;
        } else {
          hasNext = false;
          return;
        }
      } else if (child instanceof MultiVariablePattern) {
        MultiVariablePattern multiVar = (MultiVariablePattern) child;
        String name = multiVar.getName();
        varName[i] = name;
        isListVar[i] = true;
        nListVar++;

        if (!multiVar.isAnonymous() && allVars.contains(name)) {
          isBindingVar[i] = false;
        } else if (multiVar.isAnonymous()) {
          isBindingVar[i] = true;
        } else {
          allVars.add(name);
          Result<IValue> varRes = env.getVariable(name);

          if (varRes == null || multiVar.bindingInstance()) {
            isBindingVar[i] = true;
          } else {
            isBindingVar[i] = false;
            Type varType = varRes.getType();
            if (isAnyListType(varType)) {
              if (!varType.comparable(listSubjectType)) {
                hasNext = false;
                return;
              }
            } else {
              if (!(varType instanceof NonTerminalType)
                  && !(varType.comparable(staticListSubjectElementType))) {
                hasNext = false;
                return;
              }
            }
          }
        }
      } else if (child instanceof ConcreteListVariablePattern) {
        ConcreteListVariablePattern listVar = (ConcreteListVariablePattern) child;
        String name = listVar.getName();
        varName[i] = name;
        isListVar[i] = true;
        if (!listVar.isAnonymous()) allVars.add(name);
        isBindingVar[i] = true;
        listVarOccurrences[i] = 1;
        nListVar++;
      } else if (child instanceof QualifiedNamePattern) {
        QualifiedNamePattern qualName = (QualifiedNamePattern) child;
        String name = qualName.getName();
        varName[i] = name;
        if (!qualName.isAnonymous() && allVars.contains(name)) {
          /*
           * A variable that was declared earlier in the pattern
           */
          isListVar[i] = true;
          nListVar++;
          listVarOccurrences[i]++;
        } else if (qualName.isAnonymous()) {
          /*
           * Nothing to do
           */
        } else {
          Result<IValue> varRes = env.getVariable(name);

          if (varRes == null || qualName.bindingInstance()) {
            // A completely new non-list variable, nothing to do
          } else {
            Type varType = varRes.getType();
            if (isAnyListType(varType)) {
              /*
               * A variable declared in the current scope.
               */
              if (varType.comparable(listSubjectType)) {
                isListVar[i] = true;
                isBindingVar[i] = varRes.getValue() == null;
                nListVar++;
              } else {
                hasNext = false;
                return;
              }
            } else {
              if (varType instanceof NonTerminalType) {
                // suppress comparable test for Nonterminal types
                // TODO: this should be done better
              } else if (!varType.comparable(staticListSubjectElementType)) {
                hasNext = false;
                return;
              }
            }
          }
        }
      } else if (child instanceof VariableBecomesPattern) {
        // Nothing to do
      } else {
        if (debug) {
          System.err.println("List: child " + child);
          System.err.println("List: child is a" + child.getClass());
        }
        Type childType = child.getType(env, null);

        // TODO: pattern matching should be specialized such that matching appl(prod...)'s does not
        // need to use list matching on the fixed arity children of the application of a production
        if (!(childType instanceof NonTerminalType)
            && !childType.comparable(staticListSubjectElementType)) {
          hasNext = false;
          return;
        }
        java.util.List<IVarPattern> childVars = child.getVariables();
        if (!childVars.isEmpty()) {
          for (IVarPattern vp : childVars) { // TODO: This does not profit from extra information
            allVars.add(vp.name());
          }
          isListVar[i] = false;
          nListVar++;
        }
      }
    }
    /*
     * Pass #2: assign minimum and maximum length to each list variable
     */
    for (int i = 0; i < patternSize; i += delta) {
      if (isListVar[i]) {
        // TODO: reduce max length according to number of occurrences
        listVarMaxLength[i] =
            delta * Math.max(reducedSubjectSize - (reducedPatternSize - nListVar), 0);
        listVarLength[i] = 0;
        listVarMinLength[i] =
            delta
                * ((nListVar == 1) ? Math.max(reducedSubjectSize - reducedPatternSize - 1, 0) : 0);

        if (debug) {
          System.err.println(
              "listvar " + i + " min= " + listVarMinLength[i] + " max=" + listVarMaxLength[i]);
        }
      }
    }

    firstMatch = true;

    hasNext =
        subject.getValue().getType().isList()
            && reducedSubjectSize >= reducedPatternSize - nListVar;

    if (debug) {
      System.err.println("List: hasNext=" + hasNext);
    }
  }