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

  #! 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* |

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.
