nikodemus / sb-texinfo

Docstring to Texinfo tool.
http://nikodemus.github.com/sb-texinfo/
14 stars 8 forks source link

Failure in maybe-table-offset #4

Open rpgoldman opened 5 years ago

rpgoldman commented 5 years ago

I'm trying to document the SHOP2 planner, which is at https://github.com/shop-planner/shop-master

When I do

 (sb-texinfo:generate-includes "~/shop2/doc/includes/" (list :shop2 :shop2.unifier :shop2.theorem.prover :shop2.common))

I get an error in tabulation-body-p trying to write the docstring for a method. The error message is:

Invalid index -1 for (SIMPLE-VECTOR 2), should be a non-negative integer below 2.

Backtrace from sldb:

  0: (SB-TEXINFO::TABULATION-BODY-P 1 -1 #(" This SEEK-PLANS-NULL is used with WebServices to strip the add and del lists from" "the actions in the partial plan before doing the actual SEEK-PLANS-NULL...")..
  1: (SB-TEXINFO::MAYBE-TABLE-OFFSET 0 #(" This SEEK-PLANS-NULL is used with WebServices to strip the add and del lists from" "the actions in the partial plan before doing the actual SEEK-PLANS-NULL..."))
  2: (SB-TEXINFO::WRITE-TEXINFO-STRING " This SEEK-PLANS-NULL is used with WebServices to strip the add and del lists from ..)
  3: (SB-TEXINFO::WRITE-TEXINFO #<SB-TEXINFO::DOCUMENTATION (GENERIC-FUNCTION SEEK-PLANS-NULL)>)
  4: (SB-TEXINFO:GENERATE-INCLUDES "~/shop2/doc/includes/" (:SHOP2 :SHOP2.UNIFIER :SHOP2.THEOREM.PROVER :SHOP2.COMMON) :BASE-PACKAGE NIL)
  5: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SB-TEXINFO:GENERATE-INCLUDES "~/shop2/doc/includes/" (LIST :SHOP2 :SHOP2.UNIFIER :SHOP2.THEOREM.PROVER :SHOP2.COMMON)) #<NULL-LEXENV>)
  6: (EVAL (SB-TEXINFO:GENERATE-INCLUDES "~/shop2/doc/includes/" (LIST :SHOP2 :SHOP2.UNIFIER :SHOP2.THEOREM.PROVER :SHOP2.COMMON)))

I think the problem starts here :

(defun maybe-table-offset (line-number lines)
  "Return NIL or the indentation offset if LINE looks like it starts
an item in a tabulation. Ie, if it is (1) indented, (2) preceded by an
empty line, another tabulation label, or a tabulation body, (3) and
followed another tabulation label or a tabulation body."
  (let* ((line (svref lines line-number))
         (offset (indentation line))
         (prev (1- line-number)) ; <--------------
         (next (1+ line-number)))
    (when (and offset (plusp offset))
      (and (or (empty-p prev lines)
               (tabulation-body-p offset prev lines)
               (tabulation-p offset prev lines :backwards))
           (or (tabulation-body-p offset next lines)
               (tabulation-p offset next lines :forwards))
           offset))))

line-number is zero, so prev is -1 which causes a reference with (svref lines -1) in here:

(defun tabulation-body-p (offset line-number lines)
  (when (< line-number (length lines))
    (let ((offset2 (indentation (svref lines line-number)))) <-------
      (and offset2 (< offset offset2)))))

tabulation-p checks to make sure that the value of line-number is plusp, but there is no such check in tabulation-body-p. I imagine that this case is intended to be blocked by the check for empty-p. Here is empty-p:

(defun empty-p (line-number lines)
  (and (< -1 line-number (length lines))
       (not (indentation (svref lines line-number)))))

This fails because the line-number is not a valid index. The first conjunct fails, so this the previous line is treated as non-empty, and then we get the error checking for a tabulation-body.

I think that we should treat a prev of -1 as empty, but I am not sure that is the right fix:

(defun empty-p (line-number lines)
  (or (< line-number 0)
    (and (< -1 line-number (length lines))
         (not (indentation (svref lines line-number))))))
nikodemus commented 5 years ago

Sound legit.