From 126a663db298b53572efa34c63705e32a526d18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 20:07:50 +0200 Subject: [PATCH 1/8] Writeup: Detailed rationale documenting a fix. Issue: typing a character not in the keyboard in use results in a fatal crash. This writeup will document in unusual detail the steps and thoughts tracking it down. It's more-or-less live - no reset changes. Normally I would only produce the final result. And likely I would never go into this level of details. So bear with me: I'm prone to err as everyone else. Beware a mess ahead. From 891689f0a2bdb98ed82dec62e359e2be75a2ea3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 20:15:41 +0200 Subject: [PATCH 2/8] Article: Locating the issue. The binary just exists like this: $ /home/u/.cache/lambdanative/linux/calculator/calculator Thread "primordial": (list-ref '(196) 1): (Argument 1) PAIR expected $ echo $? 70 Gambit manual has to say in "2.4 Process exit status": `70' This normally indicates that an exception was raised in the primordial thread and the exception was not handled. Hence we shall look for `list-ref` in or down from the keyboard related code. $ find . -type f -exec grep --color -nH --null -e list-ref \{\} + yields among others: keypad.scm:205: (let* ((units (keypad:rowwidth (list-ref pad mn))) keypad.scm:207: (let loop ((xx (+ x padx))(data (list-ref pad mn))) keypad.scm:227: (key (keypad:lookup mx my x y w h (list-ref keypad npad))) Rationale: Hitting key results in error in list-ref -> `keypad:lookup` looks promising. Two more list-ref turning out to be within the definition of `keypad:lookup` even more. OK. "git branch" decide to go into details for the fun of it. Learn how to make empty commits for the commit message itself and start the "Article" in the form of all too frequent commits. From 35ff9912dc4510490656e5c1d1a4e0bf444625f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 20:36:23 +0200 Subject: [PATCH 3/8] Article: Taste or Rationale Looking at the definition of `keypad:lookup` I become alert even before I counciously understand what I am looking at: Line 205 contains: ")(". Having read a lot of Scheme code from various sources and knowing how easy it is to change the reader, knowing that Schemers never count parentheses and read them much like whitespace (just two kinds of them right-associative space and left-associative) there is one condition which is legal as an S-expression but still forbidden to write: an S-expression followed by an S-expression with no space or newline in between. Before I even try to dive deeper I can't help but put s space in between. --- modules/ln_glgui/keypad.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ln_glgui/keypad.scm b/modules/ln_glgui/keypad.scm index 0de7b897..fd1da846 100644 --- a/modules/ln_glgui/keypad.scm +++ b/modules/ln_glgui/keypad.scm @@ -204,7 +204,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (if (and (> my y) (< my (+ y h))) ;; (and (> mn -1) (< mn nrows)) (let* ((units (keypad:rowwidth (list-ref pad mn))) (padx (/ (- w (* units wchar)) 2.))) - (let loop ((xx (+ x padx))(data (list-ref pad mn))) + (let loop ((xx (+ x padx)) (data (list-ref pad mn))) (if (= (length data) 0) #f (let ((keyw (* wchar (keypad:keywidth (car data))))) (if (and (> mx xx) (< mx (+ xx keyw))) (car data) From 44fd38088b66040d90bf0a34d6c68ecdbe76a0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 20:49:36 +0200 Subject: [PATCH 4/8] Footnote: See SRFI-110 as example of a reader modification. From 88e9dbc17dfc5a5fe52d3915ff1ede7038698c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 21:11:47 +0200 Subject: [PATCH 5/8] Article: Code spot review. Document issues found so far. NB: When the editor re-formats a line, I no longer take that back. instead I take it as a hint to look deeper. In this case the `let* ((units` was moved. This catched attention; not more at this point. --- modules/ln_glgui/keypad.scm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/ln_glgui/keypad.scm b/modules/ln_glgui/keypad.scm index fd1da846..da8a89cb 100644 --- a/modules/ln_glgui/keypad.scm +++ b/modules/ln_glgui/keypad.scm @@ -196,16 +196,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. )) (define (keypad:lookup mx my x y w h pad) + ;; FIXME: unconfirmed: errors out in list-ref. + ;; FIXME: COMPLEXITY: O(n^2) - use of list-ref in loop (let* ((ncols (flo (length (car pad)))) (nrows (flo (length pad))) (wchar (/ w ncols)) (hchar (/ h nrows)) (mn (fix (- nrows 1 (fix (/ (- my y) hchar)))))) (if (and (> my y) (< my (+ y h))) ;; (and (> mn -1) (< mn nrows)) - (let* ((units (keypad:rowwidth (list-ref pad mn))) + (let* ((units + ;; TBD: COMPLEXITY: O(n) - use of list-ref + ;; FIXME: COMPLEXITY: O(n^2) - use of keypad:rowwidth on O(n) value + (keypad:rowwidth (list-ref pad mn))) (padx (/ (- w (* units wchar)) 2.))) (let loop ((xx (+ x padx)) (data (list-ref pad mn))) (if (= (length data) 0) #f + ;; FIXME: COMPLEXITY: O(n^2) - use of length within `keypad:keywidth` (let ((keyw (* wchar (keypad:keywidth (car data))))) (if (and (> mx xx) (< mx (+ xx keyw))) (car data) (loop (+ xx keyw) (cdr data))))))) From c49e1fd2d523fbb2d4d583677913fa491773c928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 21:17:04 +0200 Subject: [PATCH 6/8] Article: hit the re-format key The headline says it all: the editor was asked to re-format according to whatever standards. NB: If there where formatting rules attached in the file... it should follow them. Fortunately there where none. So I get the "standard" formatting I am used to. (Since I mostly follow the idea "standard is better than better" and do not customize things per-project/per-file unless forced so.) --- modules/ln_glgui/keypad.scm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/ln_glgui/keypad.scm b/modules/ln_glgui/keypad.scm index da8a89cb..1736ca19 100644 --- a/modules/ln_glgui/keypad.scm +++ b/modules/ln_glgui/keypad.scm @@ -208,14 +208,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;; TBD: COMPLEXITY: O(n) - use of list-ref ;; FIXME: COMPLEXITY: O(n^2) - use of keypad:rowwidth on O(n) value (keypad:rowwidth (list-ref pad mn))) - (padx (/ (- w (* units wchar)) 2.))) - (let loop ((xx (+ x padx)) (data (list-ref pad mn))) - (if (= (length data) 0) #f - ;; FIXME: COMPLEXITY: O(n^2) - use of length within `keypad:keywidth` - (let ((keyw (* wchar (keypad:keywidth (car data))))) - (if (and (> mx xx) (< mx (+ xx keyw))) (car data) - (loop (+ xx keyw) (cdr data))))))) - #f))) + (padx (/ (- w (* units wchar)) 2.))) + (let loop ((xx (+ x padx)) (data (list-ref pad mn))) + (if (= (length data) 0) #f + ;; FIXME: COMPLEXITY: O(n^2) - use of length within `keypad:keywidth` + (let ((keyw (* wchar (keypad:keywidth (car data))))) + (if (and (> mx xx) (< mx (+ xx keyw))) (car data) + (loop (+ xx keyw) (cdr data))))))) + #f))) (define (glgui:keypad-input g wgt type mx my) (let* ((x (glgui-widget-get-dyn g wgt 'x)) From 04fb775a83fe81953746f0dfc5279db234e089d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 21:34:05 +0200 Subject: [PATCH 7/8] Article: Summary Of First Assessment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Huston: we's got a problem. The bad news: Complexity issues are worth than load. The good news: It is small in practice. Because our keybords have only so many columns and rows and while a complexity of O(n²) is horror in principle because it does not scale, our keybords do not grow so fast as our processors become faster. The worst news so far: It's late today. The mind just does not want to try to quickly fix that. We have: 1.) code raising an exception 2.) Installing exception handler is relative expensive. Given the task there should be no need to fail in list-ref. 3.) list-ref is O(n) AND directly AND indirectly called within a loop. Question: can we understand the algorith to the extent that we can do without list-ref at all? --- modules/ln_glgui/keypad.scm | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/modules/ln_glgui/keypad.scm b/modules/ln_glgui/keypad.scm index 1736ca19..581bf13d 100644 --- a/modules/ln_glgui/keypad.scm +++ b/modules/ln_glgui/keypad.scm @@ -198,11 +198,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (define (keypad:lookup mx my x y w h pad) ;; FIXME: unconfirmed: errors out in list-ref. ;; FIXME: COMPLEXITY: O(n^2) - use of list-ref in loop - (let* ((ncols (flo (length (car pad)))) - (nrows (flo (length pad))) - (wchar (/ w ncols)) - (hchar (/ h nrows)) - (mn (fix (- nrows 1 (fix (/ (- my y) hchar)))))) + (let* ((ncols + ;; ??? what if that's not the longest line? + ;; + ;; refs: {wchar} -- `flo` in order to make `wchar` a FP? + (flo (length (car pad)))) + (nrows + ;; refs: {hchar,nm} -- `flo` in order to make `hchar` a FP? + ;; + ;; what about `nrows` in commented-out code? + (flo (length pad))) + (wchar (/ w ncols)) ;; inexact, with of character fields + (hchar (/ h nrows)) ;; inexact, height of character fields + (mn ;; ??? XXX row index + (fix (- nrows 1 (fix (/ (- my y) hchar)))))) (if (and (> my y) (< my (+ y h))) ;; (and (> mn -1) (< mn nrows)) (let* ((units ;; TBD: COMPLEXITY: O(n) - use of list-ref @@ -210,7 +219,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (keypad:rowwidth (list-ref pad mn))) (padx (/ (- w (* units wchar)) 2.))) (let loop ((xx (+ x padx)) (data (list-ref pad mn))) - (if (= (length data) 0) #f + (if (= (length data) 0) ;; FIXME: COMPLEXITY: O(n^2) - use of `length` in loop + #f ;; FIXME: COMPLEXITY: O(n^2) - use of length within `keypad:keywidth` (let ((keyw (* wchar (keypad:keywidth (car data))))) (if (and (> mx xx) (< mx (+ xx keyw))) (car data) From 9fbebf70d1f71edc3893e2be08337e0b9b3ba15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?= Date: Mon, 28 Sep 2020 21:46:09 +0200 Subject: [PATCH 8/8] Article: To Be Continued. Good Night.