 TUPLE: memo-entry ans pos ;
 C: <memo-entry> memo-entry
 
+TUPLE: left-recursion detected? ;
+C: <left-recursion> left-recursion
+ 
 : rule-parser ( rule -- parser ) 
   #! A rule is the parser compiled down to a word. It has
   #! a "peg" property containing the original parser.

  #! Store an entry in the cache
  rule-parser input-cache set-at ;

:: apply-non-memo-rule ( r p -- ast )
  [let* |
          m   [ fail p <memo-entry> dup p r set-memo ]
          ans [ r eval-rule ]
        |
    ans m (>>ans)
    pos get m (>>pos)
    ans 
  ] ;

: apply-memo-rule ( m -- ast )
  [ ans>> ] [ pos>> ] bi pos set ;

:: apply-rule ( r p -- ast )
  [let* |

  #! Return fail if the rule failed. The rule has
  #! stack effect ( input -- parse-result )
  pos get swap 
  execute 
!  drop f f <parse-result>
  [
    nip
    [ ast>> ] [ remaining>> ] bi
    input-from pos set    
