Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

815
LINES

< > BotCompany Repo | #1027178 // PhilosophyBot1 with trails [dev.]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (8939L/60K).

1  
sclass PhilosophyBot1 {
2  
  static transformable record LogicRule(lhs, rhs) {
3  
    int n; // when added
4  
    O trail;
5  
    
6  
    toString {
7  
      ret (n == 0 ? "" : "[" + n + "] ") + lhs + " => " + rhs;
8  
    }
9  
  }
10  
  static transformable record And(a, b) {}
11  
  static transformable record If(condition, thenBlock, elseBlock) {}
12  
  static transformable record For(var, condition, body) {} // don't need var actually
13  
  static transformable record ForIn(var, expr, body) {}
14  
  static transformable record While(condition, body) {}
15  
16  
  replace NPRet with O. // native predicate return type (Bool/SS/null)
17  
18  
  // like a native predicate, but doesn't return anything
19  
  sclass CodeFragment {
20  
    S head;
21  
    IVF2<SS, Env> body;
22  
    bool keepBrackets;
23  
    
24  
    *(S *head, IVF2<SS, Env> *body, bool *keepBrackets) {}
25  
    *(S *head, IVF2<SS, Env> *body) {}
26  
    
27  
    toString { ret stdToString(this); }
28  
  }
29  
30  
  sclass Env {
31  
    bool wantAlternatives;
32  
33  
    bool wantAlternatives() { ret wantAlternatives; }
34  
  }
35  
36  
  srecord WithAlternative(IF0<O> alternative, O result) {}
37  
  
38  
  // body takes variable mapping
39  
  // body can return
40  
  //   Bool => immediate result (ok or fail)
41  
  //   SS   => variable mapping
42  
  //   WithAlternative
43  
  //   Iterator<NPRet>
44  
  //   null => not applicable
45  
  // For "for $x in ..." statements, return a Iterable<stringable>?
46  
  srecord NativePredicate(S head, IF2<SS, Env, NPRet> body) {}
47  
  
48  
  replace ProcedureToRun with Proc.
49  
  replace Proc with L. // procedures are a list of statements
50  
  
51  
  // trail of a transformed fact
52  
  srecord TTransformed(S fact, IF1<S> transformer) {}
53  
54  
  transient S program;
55  
  transient bool programLoaded;
56  
  transient int maxRounds = 1000;
57  
  transient int maxFacts = 1000;
58  
  transient Set<S> facts = linkedCISet();
59  
  transient Set<S> originalFacts = ciSet();
60  
  transient new LinkedHashSet<LogicRule> logicRules; // modified with sync
61  
  transient new AllOnAll<LogicRule, S> rulesOnFacts;
62  
  transient new AllOnAll<CodeFragment, S> codeOnFacts;
63  
  transient new AllOnAll<IVF1<S>, S> anyCodeOnFacts;
64  
  transient new L<ProcedureToRun> proceduresToRun;
65  
 // parsed procedures
66  
  transient long proceduresExecuted;
67  
  transient new L<NativePredicate> nativePredicates;
68  
  transient bool debugNativeCalls = true, debugAllCmds = true;
69  
  transient bool verbose = true;
70  
  transient new L onProcedureEnded;
71  
  transient new L<IVF1<LogicRule>> onLogicRuleAdded;
72  
  transient new L<IVF1<S>> onFactAdded;
73  
  transient bool printNonMatches, debugContradictionChecks;
74  
  transient bool standardImportsLoaded;
75  
  transient bool curryAllRules = true; // rewrite "a & b => c" to a => b => c
76  
  transient int logicRulesCounter;
77  
  transient bool thoughtBegun;
78  
  transient bool printFactsAfterThinking = true;
79  
80  
  // return true when you handled adding the rule
81  
  transient new L<IPred<LogicRule>> logicRulePreprocessors;
82  
  
83  
  // return true when you handled adding the fact
84  
  transient new L<IPred<S>> factPreprocessors;
85  
  
86  
  // extra stuff that is done every round
87  
  transient new L<Runnable> extraLogicOperations;
88  
89  
  transient Set<S> vars = litciset("x", "y", "z");
90  
  
91  
  // phrase replacements that are made in every fact.
92  
  // functionality is enabled by philosophyBot1_addDeepReplacement
93  
  transient SS deepReplacements;
94  
  
95  
  transient L<IF1<S>> deepTransformers;
96  
  transient L<IF1<S, WithTrail<S>>> trailEnabledDeepTransformers;
97  
  
98  
  // fact -> trail. to enable, initialize with ciMap()
99  
  transient MapSO trails;
100  
  
101  
  Map extensions;
102  
  
103  
  *() {
104  
    // find contradictions
105  
    anyCodeOnFacts.newA(fact -> {
106  
      Bool b = checkNativeCondition(fact);
107  
      if (debugContradictionChecks)
108  
        print("Fact check: " + b + " - " + fact);
109  
      if (isFalse(b))
110  
        addFactWithTrail("contradiction", trails == null ? null : fact);
111  
    });
112  
    
113  
    _standardHandlers();
114  
  }
115  
  *(S *program) { this(); }
116  
  
117  
  void addRule(S s) {
118  
    PairS p = splitAtFirstDoubleArrow(javaTokWithBrackets(s));
119  
    if (p == null) if (verbose) print("addRule failed: " + s);
120  
    addLogicRule(new LogicRule(splitAtAmpersand2(p.a), p.b));
121  
  }
122  
  
123  
  void addRules(Iterable<S> l) {
124  
    fOr (S s : l) addRule(s);
125  
  }
126  
  
127  
  O splitRuleRHS(O rhs) {
128  
    if (rhs cast S) {
129  
      PairS p = splitAtFirstDoubleArrow(javaTokWithBrackets(rhs));
130  
      if (p != null) ret splitRuleRHS(new LogicRule(splitAtAmpersand2(p.a), splitRuleRHS(p.b)));
131  
    
132  
      ret splitAtAmpersand2(rhs);
133  
    }
134  
    ret rhs;
135  
  }
136  
  
137  
  LogicRule curryLHS(LogicRule rule) {
138  
    while licensed {
139  
      O lhs = rule.lhs;
140  
      if lhs is And(O a, O b)
141  
        rule = new LogicRule(a, new LogicRule(b, rule.rhs));
142  
      else break;
143  
    }
144  
    ret rule;
145  
  }
146  
  
147  
  void addLogicRuleWithTrail(LogicRule rule, O trail) {
148  
    rule.trail = trail;
149  
    addLogicRule(rule);
150  
  }
151  
152  
  void addLogicRule(LogicRule rule) {
153  
    rule.rhs = splitRuleRHS(rule.rhs);
154  
    
155  
    if (curryAllRules)
156  
      rule = curryLHS(rule);
157  
158  
    for (IPred<LogicRule> p : logicRulePreprocessors)
159  
      if (p.get(rule)) ret; // has been preprocessed
160  
      
161  
    rule.n = ++logicRulesCounter;
162  
      
163  
    // is LHS a native predicate? then eval immediately
164  
    // TODO: multiple conditions
165  
    Bool b = checkConditionOpt(rule.lhs);
166  
    if (isFalse(b)) ret; // drop rule
167  
    if (isTrue(b))
168  
      addRewrittenRHS(rule.rhs, rule);
169  
170  
    if (syncAdd(logicRules, rule)) {
171  
      if (verbose) print("Got logic rule", rule);
172  
      pcallFAll(onLogicRuleAdded, rule);
173  
      rulesOnFacts.newA(rule); // to combine it with the facts
174  
    }
175  
  }
176  
  
177  
  void addFacts(Iterable<S> l) {
178  
    fOr (S fact : l) addFact(fact);
179  
  }
180  
  
181  
  void addFactWithTrail(WithTrail<S> fact) {
182  
    if (fact != null) addFactWithTrail(fact!, fact.trail);
183  
  }
184  
  
185  
  void addFactWithTrail(S fact, O trail) {
186  
    addFact(fact);
187  
    mapPut(trails, fact, trail);
188  
  }
189  
190  
  void addFact(S fact) {
191  
    ping();
192  
    fact = trim(fact);
193  
    if (empty(fact)) ret;
194  
    
195  
    if (l(facts) >= maxFacts) ret;
196  
    
197  
    fact = tok_deRoundBracket(fact);
198  
    
199  
    for (IPred<S> p : factPreprocessors)
200  
      if (p.get(fact)) ret; // has been preprocessed
201  
202  
    // Check if it's a procedure
203  
    LS tok = mainTokenize(fact);
204  
    if (countCodeTokens(tok) == 2 && firstTokenEqic(tok, "proc")
205  
      && isCurlyBracketed(getCodeToken(tok, 1))) pcall {
206  
        // It's a procedure!
207  
        S proc = uncurly_keepSpaces(getCodeToken(tok, 1));
208  
        if (proceduresToRun.add(parseProcedure(proc))) {
209  
          if (verbose) print("Got procedure:");
210  
          if (verbose) print(indentx("> ", proc));
211  
        }
212  
    } /*else if (countCodeTokens(tok) == 2 && firstTokenEqic(tok, "java")
213  
      && isCurlyBracketed(getCodeToken(tok, 1))) pcall {
214  
        // It's Java code
215  
        
216  
    }*/ else // It's a fact, not a procedure
217  
      if (facts.add(fact)) {
218  
        if (verbose) print("Got fact: " + fact);
219  
        pcallFAll(onFactAdded, fact);
220  
        rulesOnFacts.newB(fact); // to combine it with the rules
221  
        codeOnFacts.newB(fact);
222  
        anyCodeOnFacts.newB(fact);
223  
      }
224  
  }
225  
226  
  void addRewrittenRHS(O o, O trail) {
227  
    if (o cast LogicRule)
228  
      addLogicRule(o);
229  
    else if o is And(O a, O b) {
230  
      addRewrittenRHS(a, o);
231  
      addRewrittenRHS(b, o);
232  
    } else if (o != null)
233  
      addFactWithTrail((S) o, trail);
234  
  }
235  
236  
  void addFactFromProgram(S fact) {  
237  
    if (countJavaTokens(fact) == 0) ret;
238  
    fact = javaDropAllComments(fact);
239  
    originalFacts.add(fact);
240  
    addFact(fact);
241  
  }
242  
243  
  void runProcedure(S proc) pcall {
244  
    if (verbose) print("Running procedure.");
245  
    runParsedProcedure(parseProcedure(proc));
246  
  }
247  
248  
  void runParsedProcedure(Proc commands) {
249  
    runParsedProcedure(commands, proceduresToRun);
250  
  }
251  
  
252  
  void runParsedProcedure(Proc commands, L<Proc> whereToPostCode) {
253  
    ++proceduresExecuted;
254  
    new Env env;
255  
    L remainingCommands = cloneLinkedList(commands);
256  
    O cmd;
257  
    while not null (cmd = popFirst_ping(remainingCommands)) {
258  
      if (cmd cast L) continue with runParsedProcedure(cmd);
259  
      if (cmd cast Runnable) continue with cmd.run();
260  
      if (debugAllCmds)
261  
        print("Running cmd: " + sfu(cmd));
262  
      if cmd is If(O condition, O thenBlock, O elseBlock) {
263  
        O blockToRun = checkCondition(condition) ? thenBlock : elseBlock;
264  
        runParsedProcedure(ll(blockToRun));
265  
      } else if cmd is For(O var, O condition, O body) {
266  
        // make a new logic rule and add it
267  
        // assume the variable is globally declared as a variable
268  
        addLogicRule(new LogicRule(condition, "proc {\n" + body + "\n}"));
269  
      } else if cmd is While(O condition, O body) {
270  
        bool b = checkCondition(condition);
271  
        if (!b) continue;
272  
        whereToPostCode.add(ll(body, cmd));
273  
      } else if cmd is ForIn(S var, S expr, O body) {
274  
        // XXX
275  
        O result = runNativePredicate(expr, new Env);
276  
        if (!result instanceof Iterable) {
277  
          if (verbose) print("Warning: result of " + expr + " not iterable (" + shortClassName(result) + ")");
278  
          continue;
279  
        }
280  
        Iterator it = iterator((Iterable) result);
281  
        Runnable step = r {
282  
          if (!it.hasNext()) ret;
283  
          S value = str(it.next());
284  
          SS map = litcimap(var, value);
285  
          O body2 = replaceVars(body, map);
286  
          //print("ForIn: " + map + " => " + body2);
287  
          whereToPostCode.add(ll(body2, this));
288  
        };
289  
        step.run();
290  
      } else if (cmd cast S) {
291  
        O result = runNativePredicate(cmd, env);
292  
        if (result != null) {
293  
          result = unpackWithAlternativeOrIterator(result);
294  
          if (isFalse(result)) ret;
295  
          if (isTrueOpt(result)) continue;
296  
          SS mapping = cast result; // assume it's a variable mapping
297  
          // apply to all remaining commands and continue
298  
          L remainingCommands2 = mapToLinkedList(remainingCommands,
299  
            c -> replaceVars(c, mapValues optRound(mapping)));
300  
          if (verbose) print("Applying var mapping " + mapping + " to " + remainingCommands
301  
            + " => " + remainingCommands2);
302  
          remainingCommands = remainingCommands2;
303  
        } else
304  
          addFact(cmd);
305  
      } else if (cmd != null)
306  
        fail("Unimplemented command: " + cmd);
307  
    }
308  
    pcallFAll(onProcedureEnded, commands); // notify listeners
309  
  }
310  
311  
  // return var mapping (SS), Bool or null for no matching predicate
312  
  // or result verbatim (e.g. Iterable)
313  
  O runNativePredicate(S s, Env env) {
314  
    for (NativePredicate np : nativePredicates) {
315  
      SS map = zipIt(np.head, s);
316  
      if (map != null) {
317  
        O result = np.body.get(mapValues tok_deRoundBracket(map), env);
318  
        if (debugNativeCalls)
319  
          print("Native predicate result: " + np.head + " => " + result);
320  
        if (result instanceof Map && nempty(map)) {
321  
          result = mapKeys((SS) result, var -> lookupOrKeep(map, var));
322  
          if (debugNativeCalls)
323  
            print("Rewrote native predicate result: " + result);
324  
        }
325  
        try object result;
326  
      } else
327  
        if (printNonMatches)
328  
          print("Non-match: " + quote(np.head) + " / " + quote(s));
329  
    }
330  
    null;
331  
  }
332  
333  
  // returns false if unknown
334  
  bool checkCondition(O o) {
335  
    ret isTrue(checkConditionOpt(o));
336  
  }
337  
  
338  
  // returns null if unknown
339  
  Bool checkConditionOpt(O o) {
340  
    if (o cast S) {
341  
      if (contains(facts, o)) true;
342  
      try object Bool b = checkNativeCondition(o);
343  
    }
344  
    //print("Ignoring condition: " + o);
345  
    null;
346  
  }
347  
  
348  
  Bool checkNativeCondition(S o) {
349  
    O result = runNativePredicate(o, new Env);
350  
    result = unpackWithAlternativeOrIterator(result);
351  
    if (result cast Bool) ret result;
352  
    if (result instanceof Map) true; // TODO
353  
    null;
354  
  }
355  
356  
  !include #1025614 // parsePythonesqueProcedure
357  
358  
  Proc parseProcedure(S s) {
359  
    ret parsePythonesqueProcedure(s);
360  
  }
361  
362  
  O splitAtAmpersand2(S s) {
363  
    LS l = tok_splitAtAmpersand(s);
364  
    if (l(l) == 1) ret s;
365  
    ret new And(first(l), splitAtAmpersand2(join(" & ", dropFirst(l))));
366  
  }
367  
368  
  // "zip" a condition with a fact (match word-by-word)
369  
  SS zipIt(S cond, S fact) {
370  
    SS map = zipIt_keepBrackets(cond, fact);
371  
    if (map == null) null; // no match
372  
    ret mapValues tok_deRoundOrCurlyBracket(map);
373  
  }
374  
  
375  
  SS zipIt_deBracket(S pat, S s) {
376  
    SS map = zipIt(pat, s);
377  
    ret map == null ? null : mapValues tok_deRoundOrCurlyBracket(map);
378  
  }
379  
380  
  // "zip" a condition with a fact (match word-by-word)
381  
  SS zipIt_keepBrackets(S cond, S fact) {
382  
    SS map = gazelle_deepZip_keepBrackets(cond, fact);
383  
    if (map == null) null; // no match
384  
    if (!all(keys(map), s -> isVar(s))) null; /*with print("Non-variable changes, exiting")*/;
385  
    ret map;
386  
  }
387  
388  
  bool isVar(S s) {
389  
    ret s != null &&
390  
      (vars.contains(s) || s.startsWith("var_") || isDollarVar(s));
391  
  }
392  
393  
  O replaceVars(O o, SS map) {
394  
    if (empty(map)) ret o;
395  
    ret transform(x -> replaceVars_base(x, map), o);
396  
  }
397  
  
398  
  O replaceVars_base(O o, SS map) {
399  
    if (o cast S)
400  
      ret replaceCodeTokensUsingMap(o, map);
401  
    null;
402  
  }
403  
  
404  
  S format(S s, SS map) {
405  
    ret replaceCodeTokensUsingMap(s, mapValues optRound(map));
406  
  }
407  
  
408  
  // if f returns null, go through structure
409  
  O transform(IF1 f, O o) {
410  
    if (o == null) null;
411  
    ping();
412  
    try object f.get(o);
413  
    
414  
    if (o cast Transformable)
415  
      ret o.transformUsing(x -> transform(f, x));
416  
    
417  
    if (o cast L)
418  
      ret map(x -> transform(f, x), o);
419  
      
420  
    fail("Don't know how to transform: " + className(o));
421  
  }
422  
423  
  void applyLogicRuleToFact(LogicRule rule, S fact) {
424  
    O lhs = rule.lhs, rhs = rule.rhs;
425  
    O cond, remaining = null;
426  
    if lhs is And(O a, O b) {
427  
      cond = a;
428  
      remaining = b;
429  
    } else
430  
      cond = lhs;
431  
    
432  
    // now we match the condition with the fact
433  
    SS map = zipIt_keepBrackets((S) cond, fact);
434  
    if (map == null) {
435  
      if (printNonMatches)
436  
        print("Non-match: " + quote(cond) + " / " + quote(fact));
437  
      ret; // no match
438  
    }
439  
440  
    // Now we have a proper mapping with the keys being variables!
441  
    if (verbose) print("Match: " + quote(cond) + " / " + quote(fact));
442  
443  
    // drop round brackets
444  
    // XXX? map = mapValues tok_deRoundBracket(map);
445  
446  
    // Apply mapping to right hand side
447  
    O rhs_replaced = replaceVars(rhs, map);
448  
    if (verbose) print(+rhs_replaced);
449  
    
450  
    Map trail = litorderedmap(op := "applyLogicRuleToFact",
451  
      +rule, +fact, +rhs_replaced, +remaining);
452  
453  
    if (remaining == null) {
454  
      // No more conditions. Add as fact / new rule
455  
      addRewrittenRHS(rhs_replaced, trail);
456  
    } else {
457  
      // Apply mapping to remaining condition
458  
      O remaining_replaced = replaceVars(remaining, map);
459  
      trail.put(+remaining_replaced);
460  
      addLogicRuleWithTrail(new LogicRule(remaining_replaced, rhs_replaced), trail);
461  
    }
462  
  }
463  
  
464  
  run { think(); }
465  
466  
  !include #1025615 // smartParser1
467  
  
468  
  void parseProgram {
469  
    if (programLoaded) ret;
470  
    set programLoaded;
471  
    loadProgram(program);
472  
  }
473  
  
474  
  void loadProgram(S program) {
475  
    smartParser1(program);
476  
  }
477  
478  
  bool doSomeLogic() {
479  
    bool anyAction;
480  
    Pair<LogicRule, S> p;
481  
    while not null (p = rulesOnFacts.next()) {
482  
      ping();
483  
      set anyAction;
484  
      //print("Combination: " + p);
485  
      applyLogicRuleToFact(p.a, p.b);
486  
    }
487  
    Pair<CodeFragment, S> p2;
488  
    while not null (p2 = codeOnFacts.next()) {
489  
      ping();
490  
      set anyAction;
491  
      //print("Combination: " + p2);
492  
      applyCodeFragmentToFact(p2.a, p2.b);
493  
    }
494  
    Pair<IVF1<S>, S> p3;
495  
    while not null (p3 = anyCodeOnFacts.next()) {
496  
      ping();
497  
      set anyAction;
498  
      //print("Combination: " + p3);
499  
      pcallF(p3.a, p3.b);
500  
    }
501  
    ret anyAction;
502  
  }
503  
504  
  void applyCodeFragmentToFact(CodeFragment cf, S fact) {
505  
    SS map = cf.keepBrackets ? zipIt_keepBrackets(cf.head, fact) : zipIt(cf.head, fact);
506  
    if (map != null)
507  
      cf.body.get(mapValues tok_deRoundBracket(map), new Env);
508  
  }
509  
  
510  
  // indicator for end of thought process (when this stays stable)
511  
  long size() {
512  
    ret l(logicRules) + l(facts) + proceduresExecuted;
513  
  }
514  
515  
  void think {
516  
    parseProgram();
517  
    
518  
    set thoughtBegun;
519  
    
520  
    int round = 0;
521  
 
522  
    while ping (round++ < maxRounds) {
523  
      long lastSize = size();
524  
      if (verbose) print("Logic round " + round + ", size: " + lastSize);
525  
      while (doSomeLogic() && round++ < maxRounds && l(facts) < maxFacts) {}
526  
527  
      for ping (Proc proc : getAndClearList(proceduresToRun))
528  
        runParsedProcedure(proc);
529  
        
530  
      callFAll(extraLogicOperations);
531  
        
532  
      if (size() == lastSize) {
533  
        if (verbose) print("No changes, exiting");
534  
        break;
535  
      }
536  
    }
537  
538  
    // We're done logicking, so print all the facts gathered
539  
540  
    Cl<S> madeFacts = factsDeduced();
541  
    if (printFactsAfterThinking)
542  
      pnlWithHeading("Facts I deduced", madeFacts);
543  
544  
    // Print say () and print () separately
545  
546  
    new LS output;
547  
    for (S fact : madeFacts) {
548  
      LS tok = mainTokenize(fact);
549  
      if (countCodeTokens(tok) == 2 && eqicOneOf(getCodeToken(tok, 0), "print", "say"))
550  
        // For the user, we print without all the round brackets
551  
        output.add(tok_dropRoundBrackets(getCodeToken(tok, 1)));
552  
    }
553  
    
554  
    pnlWithHeadingIfNempty("Bot Output", output);
555  
  }
556  
557  
  void addNativePredicate(S head, IF0 body) {
558  
    nativePredicates.add(new NativePredicate(head, (map, env) -> body!));
559  
  }
560  
  
561  
  void addNativePredicate(S head, IF1<SS, O> body) {
562  
    nativePredicates.add(new NativePredicate(head, (map, env) -> body.get(map)));
563  
  }
564  
565  
  void addNativePredicate(S head, IF2<SS, Env, NPRet> body) {
566  
    nativePredicates.add(new NativePredicate(head, body));
567  
  }
568  
569  
  // when you only need one result
570  
  O unpackWithAlternativeOrIterator(O result) {
571  
    if (result instanceof Iterator) ret first((Iterator) result);
572  
    if (result instanceof WithAlternative) ret ((WithAlternative) result).result;
573  
    ret result;
574  
  }
575  
576  
  void onFactDo(S head, IVF2<SS, Env> body) {
577  
    codeOnFacts.newA(new CodeFragment(head, body));
578  
  }
579  
580  
  void onFactDo_keepBrackets(S head, IVF2<SS, Env> body) {
581  
    codeOnFacts.newA(new CodeFragment(head, body, true));
582  
  }
583  
  
584  
  LS filterByPattern(S pat, Iterable<S> items) {
585  
    ret filter(items, i -> zipIt(pat, i) != null);
586  
  }
587  
588  
  // pat = pattern with variables
589  
  // results are mappings with debracketed values
590  
  L<SS> matchFacts(S pat) {
591  
    ret matchStrings(pat, facts);
592  
  }
593  
  
594  
  SS matchString(S pat, S input) {
595  
    ret zipIt_deBracket(pat, input);
596  
  }
597  
  
598  
  L<SS> matchStrings(S pat, Iterable<S> items) {
599  
    new L<SS> out;
600  
    for (S s : items) {
601  
      SS map = zipIt_deBracket(pat, s);
602  
      if (map != null)
603  
        out.add(map);
604  
    }
605  
    ret out;
606  
  }
607  
  
608  
  LPair<S, SS> matchFacts2(S pat) {
609  
    ret matchStrings2(pat, facts);
610  
  }
611  
  
612  
  // returns items too
613  
  LPair<S, SS> matchStrings2(S pat, Iterable<S> items) {
614  
    new LPair<S, SS> out;
615  
    for (S s : items) {
616  
      SS map = zipIt_deBracket(pat, s);
617  
      if (map != null)
618  
        out.add(pair(s, map));
619  
    }
620  
    ret out;
621  
  }
622  
  
623  
  LS matchFacts(S var, S pat) {
624  
    ret map(matchFacts(pat), map -> map.get(var));
625  
  }
626  
  
627  
  // pat = pattern with variables
628  
  // results are mappings with debracketed values
629  
  L<SS> matchFacts_keepBrackets(S pat) {
630  
    new L<SS> out;
631  
    for (S fact : facts) {
632  
      SS map = zipIt_keepBrackets(pat, fact);
633  
      if (map != null)
634  
        out.add(map);
635  
    }
636  
    ret out;
637  
  }
638  
639  
  void openAllTheories {  
640  
    for (SS map : matchFacts_keepBrackets("theory $x $y"))
641  
      openTheory(tok_deRoundOrCurlyBracket(map.get("$x")), map.get("$y"));
642  
  }
643  
  
644  
  void openTheory(S name) {
645  
    for (SS map : matchFacts_keepBrackets("theory $x $y"))
646  
      if (eqic(properUnquote(tok_deRoundBracket($x(map))), name))
647  
        ret with openTheory(name, $y(map));
648  
    fail("Theory not defined: " + quote(name));
649  
  }
650  
651  
  void openTheory(S name, S body) {
652  
    //print("Raw theory: " + quote(s));
653  
    loadProgram(withoutLeadingLinesEmptyAfterTrim_autoUnindent(tok_deRoundOrCurlyBracket_keepFirstSpacing(body)));
654  
    if (verbose) print("Opened theory " + name);
655  
  }
656  
  
657  
  void autoOpenTheories {
658  
    onFactDo_keepBrackets("theory $x $y", (map, env) -> openTheory(tok_deRoundOrCurlyBracket(map.get("$x")), map.get("$y")));
659  
  }
660  
  
661  
  // returns number of expectations checked
662  
  int checkExpectations() {
663  
    int n = 0;
664  
    // check if all expect (...) facts are met
665  
    for (SS map : matchFacts("expect $x")) {
666  
      assertContains(facts, firstValue(map));
667  
      ++n;
668  
    }
669  
    // check if all don't expect (...) facts are met
670  
    for (SS map : matchFacts("don't expect $x")) {
671  
      assertDoesntContain(facts, firstValue(map));
672  
      ++n;
673  
    }
674  
    ret n;
675  
  }
676  
  
677  
  void standardImports() {
678  
    if (standardImportsLoaded) ret;
679  
    set standardImportsLoaded;
680  
    registerImport("math", () -> philosophyBot1_math(this));
681  
    registerImport("bool", () -> philosophyBot1_bool(this));
682  
    registerImport("or", () -> philosophyBot1_orHandler(this));
683  
    registerImport("iota", () -> philosophyBot1_iotaHandler(this));
684  
    registerImport("tlft_honoringBrackets", () -> 
685  
      addNativePredicate("tlft_honoringBrackets $x",
686  
        map -> printIf(verbose, "tlft output",
687  
          tlft_honoringBrackets($x(map)))));
688  
    addNativePredicate("printNonMatches", () -> { printNonMatches = true; true; });
689  
690  
    philosophyBot1_enableAddSimplifier_withTrails(this);
691  
  }
692  
  
693  
  void addFactPreprocessor(IPred<S> f) {
694  
    factPreprocessors.add(f);
695  
  }
696  
      
697  
  void addLogicRulePreprocessor(IPred<LogicRule> f) {
698  
    logicRulePreprocessors.add(f);
699  
  }
700  
  
701  
  void registerImport(S name, Runnable handler) {
702  
    S line = "import " + name;
703  
    factPreprocessors.add(s -> {
704  
      if (eqic(s, line)) {
705  
        if (verbose) print("Importing " + name);
706  
        handler.run();
707  
        true;
708  
      }
709  
      false;
710  
    });
711  
  }
712  
  
713  
  bool hasFact(S fact) {
714  
    ret contains(facts, fact);
715  
  }
716  
  
717  
  bool hasContradiction() { ret hasFact("contradiction"); }
718  
  
719  
  LS mainTokenize(S s) {
720  
    ret javaTokWithBrackets(s);
721  
  }
722  
  
723  
  // sanitize untrusted input - overly safe version
724  
  S sanitizeInput(S s) {
725  
    ret joinWithSpace(antiFilter(words2_plusApostrophe(s), w -> isVar(w)));
726  
  }
727  
  
728  
  void deleteFacts(Iterable<S> l) {
729  
    Set<S> set = asCISet(l);
730  
    facts = filterCISet(facts, f -> !contains(set, f));
731  
  }
732  
  
733  
  Cl<S> factsDeduced() {
734  
    ret listMinusList(facts, originalFacts);
735  
  }
736  
  
737  
  bool containsDollarVars(O o) {
738  
    // abuse transform function
739  
    new Flag flag;
740  
    withCancelPoint(cp -> {
741  
      transform(x -> {
742  
        if (x cast S) {
743  
          if (main containsDollarVars(x)) {
744  
            flag.raise();
745  
            cancelTo(cp);
746  
          }
747  
          ret x;
748  
        }
749  
        null;
750  
      }, o);
751  
    });
752  
    ret flag!;
753  
  }
754  
  
755  
  L<LogicRule> allLogicRulesWithoutLHSVars() {
756  
    ret filter(logicRules, r -> !containsDollarVars(leftmostCondition(r.lhs)));
757  
  }
758  
  
759  
  O leftmostCondition(O o) {
760  
    while (o instanceof And) o = ((And) o).a;
761  
    ret o;
762  
  }
763  
  
764  
  void _standardHandlers {
765  
    philosophyBot_autoOpenTheoriesHandler(this);
766  
    addFactPreprocessor(s -> { if (eqic(s, "standard imports")) ret true with standardImports(); false; });
767  
  }
768  
  
769  
  void runAndCheckExpectations {
770  
    run();
771  
    checkExpectations();
772  
  }
773  
  
774  
  void addDeepTransformer(IF1<S> transformer) {
775  
    if (deepTransformers == null) {
776  
      deepTransformers = new L;
777  
      // enable transformers
778  
      anyCodeOnFacts.newA(fact ->
779  
        addFactWithTrail(gazelle_deepTransform(
780  
          s -> firstTransformersResult(deepTransformers, s), fact),
781  
          trails == null ? null : new TTransformed(fact, transformer)));
782  
    }
783  
    deepTransformers.add(transformer);
784  
  }
785  
  
786  
  void addTrailEnabledDeepTransformer(IF1<S, WithTrail<S>> transformer) {
787  
    if (trailEnabledDeepTransformers == null) {
788  
      trailEnabledDeepTransformers = new L;
789  
      // enable transformers
790  
      anyCodeOnFacts.newA(fact ->
791  
        addFactWithTrail(gazelle_deepTransform_withTrail(
792  
          s -> firstTransformersResult_trailEnabled(trailEnabledDeepTransformers, s), fact)));
793  
    }
794  
    trailEnabledDeepTransformers.add(transformer);
795  
  }
796  
  
797  
  O getExtension(O key) { ret mapGet(extensions, key); }
798  
  
799  
  void addExtension(O key, O value) {
800  
    if (extensions == null) extensions = new Map;
801  
    extensions.put(key, value);
802  
  }
803  
  
804  
  void enableTrails() { if (trails == null) trails = ciMap(); }
805  
  
806  
  O getTrail(S fact) { ret mapGet(trails, fact); }
807  
  
808  
  void printDeducedFactsWithTrails() {
809  
    printAsciiHeading("Deduced facts with trails");
810  
    for (S fact : factsDeduced()) {
811  
      print(fact);
812  
      printUnlessNull("  << ", getTrail(fact));
813  
    }
814  
  }
815  
}

Author comment

Began life as a copy of #1025597

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1027178
Snippet name: PhilosophyBot1 with trails [dev.]
Eternal ID of this version: #1027178/7
Text MD5: dc94a4143a8b31fd0ddfd73641fff68a
Transpilation MD5: df944bdfa1fa13f17bb758a76a42c662
Author: stefan
Category: javax / a.i.
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-02-24 12:08:02
Source code size: 25065 bytes / 815 lines
Pitched / IR pitched: No / No
Views / Downloads: 113 / 186
Version history: 6 change(s)
Referenced in: [show references]