From 613b1d5734cf119494ef5921ec86bd6cf5e3e6ea Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 15 Apr 2021 19:47:01 -0700 Subject: parse dotted lists --- shell/parse.mu | 56 +++++++++++++++++++++++ shell/sandbox.mu | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) diff --git a/shell/parse.mu b/shell/parse.mu index 357b48fb..1fc74214 100644 --- a/shell/parse.mu +++ b/shell/parse.mu @@ -57,6 +57,14 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace close-paren?, dot? <- parse-sexpression tokens, right-ah, trace return close-paren?, dot? } + # dot -> return + var dot?/eax: boolean <- dot-token? curr-token + compare dot?, 0/false + { + break-if-= + trace-higher trace + return 0/false, 1/true + } # not bracket -> parse atom var bracket-token?/eax: boolean <- bracket-token? curr-token compare bracket-token?, 0/false @@ -78,6 +86,12 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace var close-paren?/eax: boolean <- copy 0/false var dot?/ecx: boolean <- copy 0/false close-paren?, dot? <- parse-sexpression tokens, left, trace + { + compare dot?, 0/false + break-if-= + error trace, "'.' cannot be at the start of a list" + return 1/true, dot? + } compare close-paren?, 0/false break-if-!= var curr-addr/eax: (addr cell) <- lookup *curr @@ -88,6 +102,13 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace var close-paren?/eax: boolean <- copy 0/false var dot?/ecx: boolean <- copy 0/false close-paren?, dot? <- parse-sexpression tokens, tmp, trace + # '.' -> clean up right here and return + compare dot?, 0/false + { + break-if-= + parse-dot-tail tokens, curr, trace + return 0/false, 0/false + } allocate-pair curr # ')' -> return compare close-paren?, 0/false @@ -170,3 +191,38 @@ fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr t trace trace, "read", stream } } + +fn parse-dot-tail tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) { + var out/edi: (addr handle cell) <- copy _out + var close-paren?/eax: boolean <- copy 0/false + var dot?/ecx: boolean <- copy 0/false + close-paren?, dot? <- parse-sexpression tokens, out, trace + compare close-paren?, 0/false + { + break-if-= + error trace, "'. )' makes no sense" + return + } + compare dot?, 0/false + { + break-if-= + error trace, "'. .' makes no sense" + return + } + # + var dummy: (handle cell) + var dummy-ah/edi: (addr handle cell) <- address dummy + close-paren?, dot? <- parse-sexpression tokens, dummy-ah, trace + compare close-paren?, 0/false + { + break-if-!= + error trace, "cannot have multiple expressions between '.' and ')'" + return + } + compare dot?, 0/false + { + break-if-= + error trace, "cannot have two dots in a single list" + return + } +} diff --git a/shell/sandbox.mu b/shell/sandbox.mu index b127b642..0a34eb49 100644 --- a/shell/sandbox.mu +++ b/shell/sandbox.mu @@ -719,6 +719,141 @@ fn test-run-quote { check-screen-row screen, 2/y, "=> a ", "F - test-run-quote/2" } +fn test-run-dotted-list { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox, 0/no-screen-or-keyboard + # type "'(a . b)" + edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # eval + edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x80/width, 0x10/height + # + render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals + check-screen-row screen, 0/y, "'(a . b) ", "F - test-run-dotted-list/0" + check-screen-row screen, 1/y, "... ", "F - test-run-dotted-list/1" + check-screen-row screen, 2/y, "=> (a . b) ", "F - test-run-dotted-list/2" +} + +fn test-run-dot-and-list { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox, 0/no-screen-or-keyboard + # type "'(a . (b))" + edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # eval + edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x80/width, 0x10/height + # + render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals + check-screen-row screen, 0/y, "'(a . (b)) ", "F - test-run-dot-and-list/0" + check-screen-row screen, 1/y, "... ", "F - test-run-dot-and-list/1" + check-screen-row screen, 2/y, "=> (a b) ", "F - test-run-dot-and-list/2" +} + +fn test-run-final-dot { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox, 0/no-screen-or-keyboard + # type "'(a .)" + edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # eval + edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x80/width, 0x10/height + # + render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals + check-screen-row screen, 0/y, "'(a .) ", "F - test-run-final-dot/0" + check-screen-row screen, 1/y, "... ", "F - test-run-final-dot/1" + check-screen-row screen, 2/y, "'. )' makes no sense ", "F - test-run-final-dot/2" + # further errors may occur +} + +fn test-run-double-dot { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox, 0/no-screen-or-keyboard + # type "'(a . .)" + edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # eval + edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x80/width, 0x10/height + # + render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals + check-screen-row screen, 0/y, "'(a . .) ", "F - test-run-double-dot/0" + check-screen-row screen, 1/y, "... ", "F - test-run-double-dot/1" + check-screen-row screen, 2/y, "'. .' makes no sense ", "F - test-run-double-dot/2" + # further errors may occur +} + +fn test-run-multiple-expressions-after-dot { + var sandbox-storage: sandbox + var sandbox/esi: (addr sandbox) <- address sandbox-storage + initialize-sandbox sandbox, 0/no-screen-or-keyboard + # type "'(a . b c)" + edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x63/c, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # eval + edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk + # setup: screen + var screen-on-stack: screen + var screen/edi: (addr screen) <- address screen-on-stack + initialize-screen screen, 0x80/width, 0x10/height + # + render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals + check-screen-row screen, 0/y, "'(a . b c) ", "F - test-run-multiple-expressions-after-dot/0" + check-screen-row screen, 1/y, "... ", "F - test-run-multiple-expressions-after-dot/1" + check-screen-row screen, 2/y, "cannot have multiple expressions between '.' and ')' ", "F - test-run-multiple-expressions-after-dot/2" + # further errors may occur +} + fn test-run-error-invalid-integer { var sandbox-storage: sandbox var sandbox/esi: (addr sandbox) <- address sandbox-storage -- cgit 1.4.1-2-gfad0