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

930
LINES

< > BotCompany Repo | #1025597 // PhilosophyBot1 (LIVE)

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

Libraryless. Click here for Pure Java version (9584L/64K).

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

Author comment

Began life as a copy of #1025576

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1025597
Snippet name: PhilosophyBot1 (LIVE)
Eternal ID of this version: #1025597/302
Text MD5: dfbe0bae82c887f0a85d81c1ce1aebb5
Transpilation MD5: c182a034605304c1003fea5f1aa4aee8
Author: stefan
Category:
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-04-26 01:28:23
Source code size: 28551 bytes / 930 lines
Pitched / IR pitched: No / No
Views / Downloads: 763 / 2674
Version history: 301 change(s)
Referenced in: [show references]