/**
  * Constructor.
  *
  * @param builtin the invoking builtin
  * @param context the invoking rule context
  * @param message a text explanation of the error
  */
 public BuiltinException(Builtin builtin, RuleContext context, String message) {
   super(
       "Error in clause of rule ("
           + context.getRule().toShortString()
           + ") "
           + builtin.getName()
           + ": "
           + message);
 }
Exemple #2
0
 public static void init() {
   Add.init();
   Address.init();
   Align.init();
   Alloc.init();
   Anchor.init();
   And.init();
   Bad.init();
   Bitcast.init();
   Block.init();
   Builtin.init();
   Call.init();
   Cmp.init();
   Cond.init();
   Confirm.init();
   Const.init();
   Conv.init();
   CopyB.init();
   Deleted.init();
   Div.init();
   Dummy.init();
   End.init();
   Eor.init();
   Free.init();
   IJmp.init();
   Id.init();
   Jmp.init();
   Load.init();
   Member.init();
   Minus.init();
   Mod.init();
   Mul.init();
   Mulh.init();
   Mux.init();
   NoMem.init();
   Not.init();
   Offset.init();
   Or.init();
   Phi.init();
   Pin.init();
   Proj.init();
   Raise.init();
   Return.init();
   Sel.init();
   Shl.init();
   Shr.init();
   Shrs.init();
   Size.init();
   Start.init();
   Store.init();
   Sub.init();
   Switch.init();
   Sync.init();
   Tuple.init();
   Unknown.init();
 }
Exemple #3
0
  /**
   * Restore the current choice point and restart execution of the LP code until either find a
   * successful branch (in which case exit with StateFlag.ACTIVE and variables bound to the correct
   * results) or exhaust all choice points (in which case exit with StateFlag.FAIL and no bound
   * results). In future tabled version could also exit with StateFlag.SUSPEND in cases whether the
   * intepreter needs to suspend to await tabled results from a parallel proof tree.
   */
  protected StateFlag run() {
    int pc = 0; // Program code counter
    int ac = 0; // Program arg code counter
    RuleClauseCode clause = null; // The clause being executed
    ChoicePointFrame choice = null;
    byte[] code;
    Object[] args;
    boolean traceOn = engine.isTraceOn();
    boolean recordDerivations = engine.getDerivationLogging();

    main:
    while (cpFrame != null) {
      // restore choice point
      if (cpFrame instanceof ChoicePointFrame) {
        choice = (ChoicePointFrame) cpFrame;
        if (!choice.hasNext()) {
          // No more choices left in this choice point
          cpFrame = choice.getLink();
          if (traceOn)
            logger.info("FAIL in clause " + choice.envFrame.clause + " choices exhausted");
          continue main;
        }

        clause = choice.nextClause();
        // Create an execution environment for the new choice of clause
        if (recordDerivations) {
          envFrame = new EnvironmentFrameWithDerivation(clause);
        } else {
          envFrame = new EnvironmentFrame(clause);
        }
        envFrame.linkTo(choice.envFrame);
        envFrame.cpc = choice.cpc;
        envFrame.cac = choice.cac;

        // Restore the choice point state
        System.arraycopy(choice.argVars, 0, argVars, 0, RuleClauseCode.MAX_ARGUMENT_VARS);
        int trailMark = choice.trailIndex;
        if (trailMark < trail.size()) {
          unwindTrail(trailMark);
        }
        pc = ac = 0;
        if (recordDerivations) {
          ((EnvironmentFrameWithDerivation) envFrame).initDerivationRecord(argVars);
        }

        if (traceOn) logger.info("ENTER " + clause + " : " + getArgTrace());

        // then fall through into the recreated execution context for the new call

      } else if (cpFrame instanceof TripleMatchFrame) {
        TripleMatchFrame tmFrame = (TripleMatchFrame) cpFrame;

        // Restore the calling context
        envFrame = tmFrame.envFrame;
        clause = envFrame.clause;
        int trailMark = tmFrame.trailIndex;
        if (trailMark < trail.size()) {
          unwindTrail(trailMark);
        }

        // Find the next choice result directly
        if (!tmFrame.nextMatch(this)) {
          // No more matches
          cpFrame = cpFrame.getLink();
          if (traceOn) logger.info("TRIPLE match (" + tmFrame.goal + ") -> FAIL");
          continue main;
        }
        if (traceOn) {
          logger.info("TRIPLE match (" + tmFrame.goal + ") -> " + getArgTrace());
          logger.info("RENTER " + clause);
        }

        pc = tmFrame.cpc;
        ac = tmFrame.cac;

        if (recordDerivations) {
          if (envFrame instanceof EnvironmentFrameWithDerivation) {
            ((EnvironmentFrameWithDerivation) envFrame).noteMatch(tmFrame.goal, pc);
          }
        }

        // then fall through to the execution context in which the the match was called

      } else if (cpFrame instanceof TopLevelTripleMatchFrame) {
        TopLevelTripleMatchFrame tmFrame = (TopLevelTripleMatchFrame) cpFrame;

        // Find the next choice result directly
        if (!tmFrame.nextMatch(this)) {
          // No more matches
          cpFrame = cpFrame.getLink();
          if (traceOn) logger.info("TRIPLE match (" + tmFrame.goal + ") -> FAIL");
          continue main;
        } else {
          // Match but this is the top level so return the triple directly
          if (traceOn) logger.info("TRIPLE match (" + tmFrame.goal + ") ->");
          return StateFlag.SATISFIED;
        }

      } else if (cpFrame instanceof ConsumerChoicePointFrame) {
        ConsumerChoicePointFrame ccp = (ConsumerChoicePointFrame) cpFrame;

        // Restore the calling context
        envFrame = ccp.envFrame;
        clause = envFrame.clause;
        if (traceOn)
          logger.info("RESTORE " + clause + ", due to tabled goal " + ccp.generator.goal);
        int trailMark = ccp.trailIndex;
        if (trailMark < trail.size()) {
          unwindTrail(trailMark);
        }

        // Find the next choice result directly
        StateFlag state = ccp.nextMatch(this);
        if (state == StateFlag.FAIL) {
          // No more matches
          cpFrame = cpFrame.getLink();
          if (traceOn) logger.info("FAIL " + clause);
          continue main;
        } else if (state == StateFlag.SUSPEND) {
          // Require other generators to cycle before resuming this one
          preserveState(ccp);
          iContext.notifyBlockedOn(ccp);
          cpFrame = cpFrame.getLink();
          if (traceOn) logger.info("SUSPEND " + clause);
          continue main;
        }

        pc = ccp.cpc;
        ac = ccp.cac;

        if (recordDerivations) {
          if (envFrame instanceof EnvironmentFrameWithDerivation) {
            ((EnvironmentFrameWithDerivation) envFrame).noteMatch(ccp.goal, pc);
          }
        }

        // then fall through to the execution context in which the the match was called

      } else {
        throw new ReasonerException(
            "Internal error in backward rule system, unrecognized choice point");
      }

      engine.incrementProfile(clause);

      interpreter:
      while (envFrame != null) {

        // Start of bytecode intepreter loop
        // Init the state variables
        pVars = envFrame.pVars;
        int yi, ai, ti;
        Node arg, constant;
        code = clause.getCode();
        args = clause.getArgs();

        while (true) {
          switch (code[pc++]) {
            case RuleClauseCode.TEST_BOUND:
              ai = code[pc++];
              if (deref(argVars[ai]).isVariable()) {
                if (traceOn) logger.info("FAIL " + clause);
                continue main;
              }
              break;

            case RuleClauseCode.TEST_UNBOUND:
              ai = code[pc++];
              if (!deref(argVars[ai]).isVariable()) {
                if (traceOn) logger.info("FAIL " + clause);
                continue main;
              }
              break;

            case RuleClauseCode.ALLOCATE:
              int envSize = code[pc++];
              envFrame.allocate(envSize);
              pVars = envFrame.pVars;
              break;

            case RuleClauseCode.GET_VARIABLE:
              yi = code[pc++];
              ai = code[pc++];
              pVars[yi] = argVars[ai];
              break;

            case RuleClauseCode.GET_TEMP:
              ti = code[pc++];
              ai = code[pc++];
              tVars[ti] = argVars[ai];
              break;

            case RuleClauseCode.GET_CONSTANT:
              ai = code[pc++];
              arg = argVars[ai];
              if (arg instanceof Node_RuleVariable) arg = ((Node_RuleVariable) arg).deref();
              constant = (Node) args[ac++];
              if (arg instanceof Node_RuleVariable) {
                bind(arg, constant);
              } else {
                if (!arg.sameValueAs(constant)) {
                  if (traceOn) logger.info("FAIL " + clause);
                  continue main;
                }
              }
              break;

            case RuleClauseCode.GET_FUNCTOR:
              Functor func = (Functor) args[ac++];
              boolean match = false;
              Node o = argVars[2];
              if (o instanceof Node_RuleVariable) o = ((Node_RuleVariable) o).deref();
              if (Functor.isFunctor(o)) {
                Functor funcArg = (Functor) o.getLiteralValue();
                if (funcArg.getName().equals(func.getName())) {
                  if (funcArg.getArgLength() == func.getArgLength()) {
                    Node[] fargs = funcArg.getArgs();
                    for (int i = 0; i < fargs.length; i++) {
                      argVars[i + 3] = fargs[i];
                    }
                    match = true;
                  }
                }
              } else if (o.isVariable()) {
                // Construct a new functor in place
                Node[] fargs = new Node[func.getArgLength()];
                Node[] templateArgs = func.getArgs();
                for (int i = 0; i < fargs.length; i++) {
                  Node template = templateArgs[i];
                  if (template.isVariable()) template = new Node_RuleVariable(null, i + 3);
                  fargs[i] = template;
                  argVars[i + 3] = template;
                }
                Node newFunc = Functor.makeFunctorNode(func.getName(), fargs);
                bind(((Node_RuleVariable) o).deref(), newFunc);
                match = true;
              }
              if (!match) {
                if (traceOn) logger.info("FAIL " + clause);
                continue main; // fail to unify functor shape
              }
              break;

            case RuleClauseCode.UNIFY_VARIABLE:
              yi = code[pc++];
              ai = code[pc++];
              if (!unify(argVars[ai], pVars[yi])) {
                if (traceOn) logger.info("FAIL " + clause);
                continue main;
              }
              break;

            case RuleClauseCode.UNIFY_TEMP:
              ti = code[pc++];
              ai = code[pc++];
              if (!unify(argVars[ai], tVars[ti])) {
                if (traceOn) logger.info("FAIL " + clause);
                continue main;
              }
              break;

            case RuleClauseCode.PUT_NEW_VARIABLE:
              yi = code[pc++];
              ai = code[pc++];
              argVars[ai] = pVars[yi] = new Node_RuleVariable(null, yi);
              break;

            case RuleClauseCode.PUT_VARIABLE:
              yi = code[pc++];
              ai = code[pc++];
              argVars[ai] = pVars[yi];
              break;

            case RuleClauseCode.PUT_DEREF_VARIABLE:
              yi = code[pc++];
              ai = code[pc++];
              argVars[ai] = deref(pVars[yi]);
              break;

            case RuleClauseCode.PUT_TEMP:
              ti = code[pc++];
              ai = code[pc++];
              argVars[ai] = tVars[ti];
              break;

            case RuleClauseCode.PUT_CONSTANT:
              ai = code[pc++];
              argVars[ai] = (Node) args[ac++];
              break;

            case RuleClauseCode.CLEAR_ARG:
              ai = code[pc++];
              argVars[ai] = new Node_RuleVariable(null, ai);
              break;

            case RuleClauseCode.MAKE_FUNCTOR:
              Functor f = (Functor) args[ac++];
              Node[] fargs = new Node[f.getArgLength()];
              System.arraycopy(argVars, 3, fargs, 0, fargs.length);
              argVars[2] = Functor.makeFunctorNode(f.getName(), fargs);
              break;

            case RuleClauseCode.LAST_CALL_PREDICATE:
              // TODO: improved implementation of last call case
            case RuleClauseCode.CALL_PREDICATE:
              List<RuleClauseCode> clauses = ((RuleClauseCodeList) args[ac++]).getList();
              // Check if this call is now grounded
              boolean groundCall =
                  isGrounded(argVars[0]) && isGrounded(argVars[1]) && isGrounded(argVars[2]);
              setupClauseCall(pc, ac, clauses, groundCall);
              setupTripleMatchCall(pc, ac);
              continue main;

            case RuleClauseCode.CALL_PREDICATE_INDEX:
              // This code path is experimental, don't yet know if it has enough
              // performance benefit to justify the cost of maintaining it.
              clauses = ((RuleClauseCodeList) args[ac++]).getList();
              // Check if we can futher index the clauses
              if (!argVars[2].isVariable()) {
                clauses =
                    engine
                        .getRuleStore()
                        .codeFor(new TriplePattern(argVars[0], argVars[1], argVars[2]));
              }
              setupClauseCall(pc, ac, clauses, false);
              setupTripleMatchCall(pc, ac);
              continue main;

            case RuleClauseCode.CALL_TRIPLE_MATCH:
              setupTripleMatchCall(pc, ac);
              continue main;

            case RuleClauseCode.CALL_TABLED:
              setupTabledCall(pc, ac);
              continue main;

            case RuleClauseCode.CALL_WILD_TABLED:
              Node predicate = deref(argVars[1]);
              if (engine.getRuleStore().isTabled(predicate)) {
                setupTabledCall(pc, ac);
              } else {
                // normal call set up
                clauses =
                    engine
                        .getRuleStore()
                        .codeFor(new TriplePattern(argVars[0], predicate, argVars[2]));
                if (clauses != null) setupClauseCall(pc, ac, clauses, false);
                setupTripleMatchCall(pc, ac);
              }
              continue main;

            case RuleClauseCode.PROCEED:
              pc = envFrame.cpc;
              ac = envFrame.cac;
              if (traceOn) logger.info("EXIT " + clause);
              if (choice != null) choice.noteSuccess();
              if (recordDerivations && envFrame.getRule() != null) {
                if (envFrame instanceof EnvironmentFrameWithDerivation) {
                  EnvironmentFrameWithDerivation efd = (EnvironmentFrameWithDerivation) envFrame;
                  Triple result = efd.getResult();
                  List<Triple> matches = efd.getMatchList();
                  BackwardRuleInfGraphI infGraph = engine.getInfGraph();
                  RuleDerivation d =
                      new RuleDerivation(envFrame.getRule(), result, matches, infGraph);
                  infGraph.logDerivation(result, d);

                  // Also want to record this result in the calling frame
                  if (envFrame.link instanceof EnvironmentFrameWithDerivation) {
                    EnvironmentFrameWithDerivation pefd =
                        (EnvironmentFrameWithDerivation) envFrame.link;
                    pefd.noteMatch(new TriplePattern(result), pc);
                  }
                }
              }
              envFrame = (EnvironmentFrame) envFrame.link;
              if (envFrame != null) {
                clause = envFrame.clause;
              }
              continue interpreter;

            case RuleClauseCode.CALL_BUILTIN:
              Builtin builtin = (Builtin) args[ac++];
              if (context == null) {
                BBRuleContext bbcontext = new BBRuleContext(engine.getInfGraph());
                bbcontext.setEnv(new LPBindingEnvironment(this));
                context = bbcontext;
              }
              context.setRule(clause.getRule());
              if (!builtin.bodyCall(argVars, code[pc++], context)) {
                if (traceOn) logger.info("FAIL " + clause + ", due to " + builtin.getName());
                continue main;
              }
              break;

            default:
              throw new ReasonerException(
                  "Internal error in backward rule system\nIllegal op code");
          }
        }
        // End of innter code loop
      }
      // End of bytecode interpreter loop, gets to here if we complete an AND chain
      return StateFlag.ACTIVE;
    }
    // Gets to here if we have run out of choice point frames
    return StateFlag.FAIL;
  }
Exemple #4
0
    @Override
    public Object execute(Frame frame) {

      RAny lhsVal = (RAny) lhs.execute(frame);
      Object rowFromVal = rowFromExpr.execute(frame);
      Object rowToVal = rowToExpr.execute(frame);
      Object colFromVal = colFromExpr.execute(frame);
      Object colToVal = colToExpr.execute(frame);
      boolean dropVal =
          dropExpr.executeLogical(frame)
              != RLogical.FALSE; // FIXME: what is the correct execution order of these args?
      int exactVal = exactExpr.executeLogical(frame);
      if (!(lhsVal instanceof RArray)) {
        throw RError.getObjectNotSubsettable(ast, lhsVal.typeOf());
      }
      RArray array = (RArray) lhsVal;

      try {

        int rowFrom = extractLimit(rowFromVal); // zero-based
        int rowTo = extractLimit(rowToVal);
        int colFrom = extractLimit(colFromVal);
        int colTo = extractLimit(colToVal);

        int[] dim = array.dimensions();
        if (dim == null || dim.length != 2) {
          throw RError.getIncorrectDimensions(getAST());
        }
        int m = dim[0];
        int n = dim[1];

        int rowStep;
        int rowSize;
        if (rowFrom <= rowTo) {
          rowStep = 1;
          if (rowTo > m) {
            throw new UnexpectedResultException(null);
          }
          rowSize = rowTo - rowFrom + 1;
        } else {
          rowStep = -1;
          if (rowFrom > m) {
            throw new UnexpectedResultException(null);
          }
          rowSize = rowFrom - rowTo + 1;
        }

        int colStep;
        int colSize;
        if (colFrom <= colTo) {
          colStep = 1;
          if (colTo > n) {
            throw new UnexpectedResultException(null);
          }
          colSize = colTo - colFrom + 1;
        } else {
          colStep = -1;
          if (colFrom > n) {
            throw new UnexpectedResultException(null);
          }
          colSize = colFrom - colTo + 1;
        }

        int[] ndim;
        if (!dropVal || (rowSize > 1 && colSize > 1)) {
          ndim = new int[] {rowSize, colSize};
        } else {
          ndim = null;
        }

        int size = rowSize * colSize;
        RArray res = Utils.createArray(array, size, ndim, null, null); // drop attributes

        if (colStep == 1 && rowStep == 1) {
          int j = colFrom * m + rowFrom; // j - index to source matrix
          int jmax = j + rowSize;
          int jadvance = m - rowSize;
          for (int i = 0; i < size; i++) {
            res.set(i, array.getRef(j++)); // i - index to target matrix
            if (j == jmax) {
              j += jadvance;
              jmax += m;
            }
          }
        } else {
          int i = 0;
          // NOTE: here we know that colFrom != colTo and rowFrom != rowTo
          for (int col = colFrom; col != colTo + colStep; col += colStep) {
            for (int row = rowFrom; row != rowTo + rowStep; row += rowStep) {
              res.set(i++, array.getRef(col * m + row));
            }
          }
        }
        return res;
      } catch (UnexpectedResultException e) {
        // FIXME: clean this up; does Colon need to be package-private?
        ASTNode rowAST = rowFromExpr.getAST().getParent();
        Builtin rowColon =
            (Builtin)
                Primitives.getCallFactory(RSymbol.getSymbol(":"), null)
                    .create(rowAST, rowFromExpr, rowToExpr);
        SelectorNode selIExpr = Selector.createSelectorNode(rowAST, true, rowColon);
        ASTNode colAST = colFromExpr.getAST().getParent();
        Builtin colColon =
            (Builtin)
                Primitives.getCallFactory(RSymbol.getSymbol(":"), null)
                    .create(colAST, colFromExpr, colToExpr);
        SelectorNode selJExpr = Selector.createSelectorNode(ast, true, colColon);
        MatrixRead nn = new MatrixRead(ast, true, lhs, selIExpr, selJExpr, dropExpr, exactExpr);
        replace(nn, "install MatrixRead from MatrixSequenceSubset");
        Selector selI =
            selIExpr.executeSelector(
                rowColon.doBuiltIn(frame, new RAny[] {(RAny) rowFromVal, (RAny) rowToVal}));
        Selector selJ =
            selJExpr.executeSelector(
                colColon.doBuiltIn(frame, new RAny[] {(RAny) colFromVal, (RAny) colToVal}));
        return nn.executeLoop(array, selI, selJ, dropVal, exactVal);
      }
    }