public CGExpr[] PEvalArgs(PEnv pEnv, bool hasDynamicControl) { CGExpr[] res = new CGExpr[es.Length]; for (int i = 0; i < es.Length; i++) { res[i] = es[i].PEval(pEnv, hasDynamicControl); } return res; }
// Partially evaluate the programList with respect to the given static inputs, // producing a new ProgramLines object. public ProgramLines PEval(Value[] args, FullCellAddr[] residualInputs) { PEnv pEnv = new PEnv(); // Map static input cells to their constant values: for (int i = 0; i < args.Length; i++) { pEnv[inputCells[i]] = CGConst.Make(args[i]); } ProgramLines residual = new ProgramLines(outputCell, residualInputs); // PE-time environment PEnv maps each residual input cell address to the delegate argument: for (int i = 0; i < residualInputs.Length; i++) { FullCellAddr input = residualInputs[i]; pEnv[input] = new CGCellRef(input, residual.addressToVariable[input]); } // Process the given function's compute cells in dependency order, output last: foreach (ComputeCell ccell in programList) { ComputeCell rCcell = ccell.PEval(pEnv); if (rCcell != null) { residual.AddComputeCell(ccell.cellAddr, rCcell); } } residual = residual.PruneZeroUseCells(); return(residual); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // When FunctionValue is known, reduce to a CGSdfCall node. // Don't actually call the function (even on constant arguments); could loop. CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl); if (res[0] is CGValueConst) { FunctionValue fv = (res[0] as CGValueConst).Value as FunctionValue; if (fv != null) { CGExpr[] args = new CGExpr[fv.args.Length]; int j = 1; for (int i = 0; i < args.Length; i++) { if (fv.args[i] != ErrorValue.naError) { args[i] = CGConst.Make(fv.args[i]); } else { args[i] = res[j++]; } } return(new CGSdfCall(fv.sdfInfo, args)); } else { return(new CGError(ErrorValue.argCountError)); } } else { return(new CGApply(res)); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // When FunctionValue is known, reduce to a CGSdfCall node. // Don't actually call the function (even on constant arguments); could loop. CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl); if (res[0] is CGValueConst) { FunctionValue fv = (res[0] as CGValueConst).Value as FunctionValue; if (fv != null) { CGExpr[] args = new CGExpr[fv.args.Length]; int j = 1; for (int i = 0; i < args.Length; i++) { if (fv.args[i] != ErrorValue.naError) { args[i] = CGConst.Make(fv.args[i]); } else { args[i] = res[j++]; } } return new CGSdfCall(fv.sdfInfo, args); } else { return new CGError(ErrorValue.argCountError); } } else { return new CGApply(res); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { List <CGExpr> res = new List <CGExpr>(); for (int i = 0; i < es.Length; i++) { CGExpr ri = es[i].PEval(pEnv, hasDynamicControl || res.Count > 0); if (ri is CGNumberConst) { // A TRUE operand makes the OR true; a FALSE operand can be ignored if ((ri as CGNumberConst).number.value != 0.0) { return(new CGNumberConst(NumberValue.ONE)); } } else { res.Add(ri); } } // The residual OR consists of the non-constant operands, if any if (res.Count == 0) { return(new CGNumberConst(NumberValue.ZERO)); } else { return(new CGOr(res.ToArray())); } }
public ProveResult TripleQuery(Term thisTerm, PartListImpl goalList, PEnv environment, PDB db, int level, reportDelegate reportFunction) { // bagof(Term, ConditionTerm, ReturnList) // PartList goalList = (PartList)goalIn; Part collect0 = value((Part)thisTerm.ArgList[0], environment); Part subgoal = value((Part)thisTerm.ArgList[1], environment); Part into = value((Part)thisTerm.ArgList[2], environment); Part collect = renameVariables(collect0, level, thisTerm); //var newGoal = new Term(subgoal.name, renameVariables(subgoal.ArgList, level, thisTerm)); Term newGoal = new Term(subgoal.fname, false, (PartListImpl)renameVariables(((PartListImpl)subgoal), level, thisTerm)); newGoal.parent = thisTerm; //var newGoals = []; //newGoals[0] = newGoal; PartListImpl newGoals = new PartListImpl(); newGoals.AddPart(newGoal); // Prove this subgoal, collecting up the environments... PartListImpl anslist = new PartListImpl(); anslist.renumber = -1; var ret = prove(newGoals, environment, db, level + 1, BagOfCollectFunction(collect, anslist)); // Turn anslist into a proper list and unify with 'into' // optional here: nil anslist -> fail? Part answers = Atom.FromSource(FUNCTOR_NIL); /* * print("Debug: anslist = ["); * for (var j = 0; j < anslist.length; j++) { * anslist[j].print(); * print(", "); * } * print("]\n"); */ for (int i = anslist.Arity; i > 0; i--) { answers = MakeList(anslist.ArgList[i - 1], answers); } //print("Debug: unifying "); into.print(); print(" with "); answers.print(); print("\n"); var env2 = unify(into, answers, environment); if (env2 == null) { //print("Debug: bagof cannot unify anslist with "); into.print(); print(", failing\n"); return(null); } // Just prove the rest of the goallist, recursively. return(prove(goalList, env2, db, level + 1, reportFunction)); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl); // The static argument positions are those that have args[i] != naError Value[] args = new Value[res.Length]; bool anyStatic = false, allStatic = true; for (int i = 0; i < res.Length; i++) { if (res[i] is CGConst) { args[i] = (res[i] as CGConst).Value; anyStatic = true; } else { args[i] = ErrorValue.naError; // Generalize to dynamic allStatic = false; } } if (!hasDynamicControl) { // This would be wrong, because the called function might contain // volatile functions and in that case should residualize: // if (allStatic) // If all arguments static, just call the SDF // return CGConst.Make(sdfInfo.Apply(args)); // else if (anyStatic) // Specialize if there are static arguments { return(Specialize(res, args)); } // Do nothing if all arguments are dynamic } else { // If under dynamic control reduce to longest static prefix // where the argument values agree. // TODO: This is wrong -- should always specialize when the call is not // recursive ICollection <Value[]> pending = SdfManager.PendingSpecializations(sdfInfo.name); Value[] maxArray = null; int maxCount = 0; foreach (Value[] vs in pending) { int agree = AgreeCount(vs, args); if (agree > maxCount) { maxCount = agree; maxArray = vs; } } if (maxCount > 0) { SetNaInArgs(maxArray, args); return(Specialize(res, args)); } } return(new CGSdfCall(sdfInfo, res)); }
public PartListImpl(PartListImpl head, PEnv env) { this.tlist = new List <Part>(); for (var i = 0; i < head.Count; i++) { tlist.Add(value(head[i], env)); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // Volatile functions must be residualized if (functionInfo.name == "NOW" || functionInfo.name == "RAND") { return Residualize(PEvalArgs(pEnv, hasDynamicControl)); } else { return base.PEval(pEnv, hasDynamicControl); } }
public CGExpr[] PEvalArgs(PEnv pEnv, bool hasDynamicControl) { CGExpr[] res = new CGExpr[es.Length]; for (int i = 0; i < es.Length; i++) { res[i] = es[i].PEval(pEnv, hasDynamicControl); } return(res); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // Partial evaluation may encounter a cached expression in conditionals // etc, and should simply partially evaluate the expression inside the cache. // No duplication of cached expression happens in the residual program because // a cached expression appears only once in the regular code, and no occurrence // from evaluation conditions is added to the residual program; see ComputeCell.PEval. // New evaluation conditions are added later; see ProgramLines.CompileToDelegate. return(expr.PEval(pEnv, hasDynamicControl)); }
public ProveResult ExecuteSharp(Term thisTerm, PartListImpl goalList, PEnv environment, PDB db, int level, reportDelegate reportFunction) { Term collect0 = value((Part)thisTerm.ArgList[1], environment).AsTerm(); string methodName = collect0.fname; var partObj = value((Part)thisTerm.ArgList[0], environment); object result; TextWriter warns = new StringWriter(); try { if (partObj.IsObject) { if (!CanInvokeObject(partObj.Functor0, methodName, collect0.ArgList, out result, warns)) { Warn(warns); return(new ProveResult() { Failed = true }); } } else { if (!CanInvokeObjectByName(partObj.Text, methodName, collect0.ArgList, true, out result, warns)) { Warn(warns); return(new ProveResult() { Failed = true }); } } } catch (Exception e2) { Warn(warns); throw e2; return(new ProveResult() { Failed = true }); } //print("Debug: unifying "); into.print(); print(" with "); answers.print(); print("\n"); var env2 = unify(thisTerm.ArgList[2], ObjectToPart(result), environment); if (env2 == null) { //print("Debug: bagof cannot unify anslist with "); into.print(); print(", failing\n"); return(null); } // Just prove the rest of the goallist, recursively. return(prove(goalList, env2, db, level + 1, reportFunction)); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // Volatile functions must be residualized if (functionInfo.name == "NOW" || functionInfo.name == "RAND") { return(Residualize(PEvalArgs(pEnv, hasDynamicControl))); } else { return(base.PEval(pEnv, hasDynamicControl)); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr r0 = es[0].PEval(pEnv, hasDynamicControl); if (r0 is CGNumberConst) { if ((r0 as CGNumberConst).number.value != 0.0) { return es[1].PEval(pEnv, hasDynamicControl); } else { return es[2].PEval(pEnv, hasDynamicControl); } } else { return new CGIf(PEvalArgs(pEnv, r0, true)); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl); // The static argument positions are those that have args[i] != naError Value[] args = new Value[res.Length]; bool anyStatic = false, allStatic = true; for (int i = 0; i < res.Length; i++) { if (res[i] is CGConst) { args[i] = (res[i] as CGConst).Value; anyStatic = true; } else { args[i] = ErrorValue.naError; // Generalize to dynamic allStatic = false; } } if (!hasDynamicControl) { // This would be wrong, because the called function might contain // volatile functions and in that case should residualize: // if (allStatic) // If all arguments static, just call the SDF // return CGConst.Make(sdfInfo.Apply(args)); // else if (anyStatic) // Specialize if there are static arguments { return Specialize(res, args); } // Do nothing if all arguments are dynamic } else { // If under dynamic control reduce to longest static prefix // where the argument values agree. // TODO: This is wrong -- should always specialize when the call is not // recursive ICollection<Value[]> pending = SdfManager.PendingSpecializations(sdfInfo.name); Value[] maxArray = null; int maxCount = 0; foreach (Value[] vs in pending) { int agree = AgreeCount(vs, args); if (agree > maxCount) { maxCount = agree; maxArray = vs; } } if (maxCount > 0) { SetNaInArgs(maxArray, args); return Specialize(res, args); } } return new CGSdfCall(sdfInfo, res); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr r0 = es[0].PEval(pEnv, hasDynamicControl); if (r0 is CGNumberConst) { int index = (int)((r0 as CGNumberConst).number.value); if (index < 1 || index >= es.Length) { return new CGError(ErrorValue.valueError); } else { return es[index].PEval(pEnv, hasDynamicControl); } } else { return new CGChoose(PEvalArgs(pEnv, r0, true /* has dynamic control */)); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl); // If all args are constant then evaluate else residualize: if (AllConstant(res)) { Expr[] es = new Expr[res.Length]; for (int i = 0; i < res.Length; i++) { es[i] = Const.Make((res[i] as CGConst).Value); } // Use the interpretive implementation's applier on a fake sheet // and fake cell coordinates, but constant argument expressions: return CGConst.Make(applier(null, es, -1, -1)); } else { return Residualize(res); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr[] res = PEvalArgs(pEnv, hasDynamicControl); // If all args are constant then evaluate else residualize: if (AllConstant(res)) { Expr[] es = new Expr[res.Length]; for (int i = 0; i < res.Length; i++) { es[i] = Const.Make((res[i] as CGConst).Value); } // Use the interpretive implementation's applier on a fake sheet // and fake cell coordinates, but constant argument expressions: return(CGConst.Make(applier(null, es, -1, -1))); } else { return(Residualize(res)); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr r0 = es[0].PEval(pEnv, hasDynamicControl); if (r0 is CGNumberConst) { if ((r0 as CGNumberConst).number.value != 0.0) { return(es[1].PEval(pEnv, hasDynamicControl)); } else { return(es[2].PEval(pEnv, hasDynamicControl)); } } else { return(new CGIf(PEvalArgs(pEnv, r0, true))); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { CGExpr r0 = es[0].PEval(pEnv, hasDynamicControl); if (r0 is CGNumberConst) { int index = (int)((r0 as CGNumberConst).number.value); if (index < 1 || index >= es.Length) { return(new CGError(ErrorValue.valueError)); } else { return(es[index].PEval(pEnv, hasDynamicControl)); } } else { return(new CGChoose(PEvalArgs(pEnv, r0, true /* has dynamic control */))); } }
// Returns residual ComputeCell or null if no cell needed public ComputeCell PEval(PEnv pEnv) { CGExpr rCond = null; if (evalCond != null) // Never the case for an output cell { rCond = evalCond.PEval(pEnv, false /* not dynamic control */); } if (rCond is CGNumberConst) { if ((rCond as CGNumberConst).number.value != 0.0) { rCond = null; // eval cond constant TRUE, discard eval cond } else { return(null); // eval cond constant FALSE, discard entire compute cell } } // If residual eval cond is not TRUE then expr has dynamic control CGExpr rExpr = expr.PEval(pEnv, rCond != null); if (rExpr is CGConst && var != null) { // If cell's value is constant and it is not an output cell just put in PEnv pEnv[cellAddr] = rExpr; return(null); } else { // Else create fresh local variable for the residual cell, and make // PEnv map cell address to that local variable: Variable newVar = var != null?var.Fresh() : null; pEnv[cellAddr] = new CGCellRef(cellAddr, newVar); ComputeCell result = new ComputeCell(rExpr, newVar, cellAddr); // result.EvalCond = rCond; // Don't save residual eval cond, we compute it accurately later... return(result); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { List<CGExpr> res = new List<CGExpr>(); for (int i = 0; i < es.Length; i++) { CGExpr ri = es[i].PEval(pEnv, hasDynamicControl || res.Count > 0); if (ri is CGNumberConst) { // A TRUE operand makes the OR true; a FALSE operand can be ignored if ((ri as CGNumberConst).number.value != 0.0) { return new CGNumberConst(NumberValue.ONE); } } else { res.Add(ri); } } // The residual OR consists of the non-constant operands, if any if (res.Count == 0) { return new CGNumberConst(NumberValue.ZERO); } else { return new CGOr(res.ToArray()); } }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { return(pEnv[cellAddr]); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { return this; }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { return pEnv[cellAddr]; }
// Returns residual ComputeCell or null if no cell needed public ComputeCell PEval(PEnv pEnv) { CGExpr rCond = null; if (evalCond != null) // Never the case for an output cell { rCond = evalCond.PEval(pEnv, false /* not dynamic control */); } if (rCond is CGNumberConst) { if ((rCond as CGNumberConst).number.value != 0.0) { rCond = null; // eval cond constant TRUE, discard eval cond } else { return null; // eval cond constant FALSE, discard entire compute cell } } // If residual eval cond is not TRUE then expr has dynamic control CGExpr rExpr = expr.PEval(pEnv, rCond != null); if (rExpr is CGConst && var != null) { // If cell's value is constant and it is not an output cell just put in PEnv pEnv[cellAddr] = rExpr; return null; } else { // Else create fresh local variable for the residual cell, and make // PEnv map cell address to that local variable: Variable newVar = var != null ? var.Fresh() : null; pEnv[cellAddr] = new CGCellRef(cellAddr, newVar); ComputeCell result = new ComputeCell(rExpr, newVar, cellAddr); // result.EvalCond = rCond; // Don't save residual eval cond, we compute it accurately later... return result; } }
// Partially evaluate the programList with respect to the given static inputs, // producing a new ProgramLines object. public ProgramLines PEval(Value[] args, FullCellAddr[] residualInputs) { PEnv pEnv = new PEnv(); // Map static input cells to their constant values: for (int i = 0; i < args.Length; i++) { pEnv[inputCells[i]] = CGConst.Make(args[i]); } ProgramLines residual = new ProgramLines(outputCell, residualInputs); // PE-time environment PEnv maps each residual input cell address to the delegate argument: for (int i = 0; i < residualInputs.Length; i++) { FullCellAddr input = residualInputs[i]; pEnv[input] = new CGCellRef(input, residual.addressToVariable[input]); } // Process the given function's compute cells in dependency order, output last: foreach (ComputeCell ccell in programList) { ComputeCell rCcell = ccell.PEval(pEnv); if (rCcell != null) { residual.AddComputeCell(ccell.cellAddr, rCcell); } } residual = residual.PruneZeroUseCells(); return residual; }
/// <summary> /// Specialize the expression with respect to the values/residual expressions in pEnv. /// </summary> /// <param name="pEnv">Maps cell addresses to already-specialized expressions</param> /// <returns>The specialized expression</returns> public abstract CGExpr PEval(PEnv pEnv, bool hasDynamicControl);
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // Always residualize; external function could have effects or be volatile return(new CGExtern(PEvalArgs(pEnv, hasDynamicControl))); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // Always residualize; external function could have effects or be volatile return new CGExtern(PEvalArgs(pEnv, hasDynamicControl)); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { return(this); }
public override CGExpr PEval(PEnv pEnv, bool hasDynamicControl) { // Partial evaluation may encounter a cached expression in conditionals // etc, and should simply partially evaluate the expression inside the cache. // No duplication of cached expression happens in the residual program because // a cached expression appears only once in the regular code, and no occurrence // from evaluation conditions is added to the residual program; see ComputeCell.PEval. // New evaluation conditions are added later; see ProgramLines.CompileToDelegate. return expr.PEval(pEnv, hasDynamicControl); }