/** * 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); }
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(); }
/** * 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; }
@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); } }