let !!$ x !!!!!!compute 'x !!!!y !!!!!!compute 'y !!use x y ==>
let INDENT INDENT x ; stack: (0 2 ?) INDENT compute 'x ; stack: (0 2 ? 6) DEDENT ; stack: (0 2 ?), indentation = 4 y ; stack: (0 2 4) INDENT compute 'y ; stack (0 2 4 6) DEDENT DEDENT ; stack (0 2) use x y DEDENT ==> let !\\ !!x !!!compute 'x !!y !!!compute 'y !use x y --- Hmmm..... let !!$ x (compute 'x) !!!!y (compute 'y) !!use x y ===> let INDENT INDENT x (compute 'x) ; stack: (0 2 ?) INDENT y (compute 'y) ; stack: (0 2 ? 4) - bummer!!!!!!!! DEDENT DEDENT ; stack: (0 2) use x y DEDENT ====> let !\\ !!x (compute 'x) !!!y (compute 'y) !use x y bummer!!!! On 2/19/13, Alan Manuel Gloria <almkg...@gmail.com> wrote: > On 2/19/13, Beni Cherniavsky-Paskin <c...@users.sf.net> wrote: >> Here is yet another idea for opening multiple levels on one line, that >> does >> NOT involve column counting, only comparison of leading whitespaces. >> >> It's a backward-compatible extension to SUBLIST (similarly applicable to >> any competing FOOLIST semantics), so we could leave it undecided for now, >> and legalize it later. >> >> $ lets one open an inner list on one line, but currently it's only usable >> when this list is the last element of the containing list: >> >> outer1 outer2 $ inner1 >> ! inner2 >> >> You cannot express (outer1 outer2 (inner1 inner2) outer3) >> without giving up on use of $. >> >> The proposal is to allow an unmatched dedent after inner2, and have that >> return you to the outer level: >> >> outer1 outer2 $ inner1 >> ! ! inner2 >> ! outer3 >> >> which would be equivallent to: >> >> outer1 outer2 >> ! inner1 >> ! ! inner2 >> ! outer3 >> >> More formally (described for simplicity in terms of numeric indentation >> levels; easily doable in terms of exact substrings): >> >> - Every $ pushes a "?" placeholder onto the stack of known indent levels. >> - As before, increases in indentation push a specific number onto the >> stack. >> - Dedents matching a level on the stack are handled as before, closing >> all >> levels to the right, whether specific or placeholders. >> - A dedent that doesn't match any specific level is *only* allowed if >> there >> is at least one placeholder between the closest specific levels. All >> higher levels are closed, and the *rightmost* (see rationate at end) of >> these placeholders is converted to the specific level seen. >> Let's say you had (10 ? ? 16) on the stack and you encounter a line >> starting with 14 spaces. This closes 16 and the new stack is (10 ? 14). >> A following 13 line would close 14 and leave (10 13), and then a >> following 12 line would be an error. > > I think it's also important to consider the "SAME" (as opposed to > INDENT or DEDENT) token. In particular: > > x > ! foo $ bar > ! a b > > ==> > > (x > (foo bar) > (a b) > ) > > Since the INDENT/SAME/DEDENT decision is based on the indentation > stack, I think we should specify it as follows: > > 1. Every $ adds a ? to the indentation stack, and emits an INDENT. > 2. On encountering an EOL, slurp the indentation. > 3. If the indentation is greater than the topmost non-? stack entry, > push its indentation level on the stack and consider it an INDENT. > 4. If the indentation is equal to the topmost non-? stack entry, pop > off ? stack entries (emitting a DEDENT for each). If there are no ? > on the stack top, emit a SAME. > 5. If the indentation is less than the topmost non-? stack entry, pop > off ? stack entries (emitting a DEDENT for each) until you reach a > state where the topmost non-? stack entry is less than or equal to the > indentation. > 5.1. If the topmost non-? stack entry is equal to the indentation, > pop off ? stack entries (emitting a DEDENT for each). > 5.2. if the topmost non-? stack entry is less than the indentation, > and there is at least one ? entry, pop off the topmost ? entry and > replace it with the current indentation (do not emit any INDENT or > DEDENT tokens). > 5.2. Otherwise, error! > > So, let's consider this classic SUBLIST text: > > probe $ call/cc $ lambda (exit) $ cond > foo? $ exit 1 > bar? $ 2 > > ==> > probe INDENT call/cc INDENT lambda (exit) INDENT cond > ; at this stage, stack is (0 ? ? ?) > INDENT foo? INDENT exit 1 > ; at this stage, stack is (0 ? ? ? 2 ?) > ; it sees an indent of 2, so it emits a DEDENT here > ; via rule #4. > DEDENT > bar? INDENT 2 > ; at this stage, stack is (0 ? ? ? 2 ?) > ; an empty line may be considered an indent of 0, > ; so insert 5 DEDENT's > DEDENT DEDENT DEDENT DEDENT DEDENT > > ==> > probe > ! call/cc > ! ! lambda (exit) > ! ! ! cond > ! ! ! ! foo? > ! ! ! ! ! exit 1 ; 5 indent's so far, so 5 levels, seems right > ! ! ! ! bar? > ! ! ! ! ! 2 ; 5 dedents after this, so we close!! > > -- > > Looks about right. > > Now the main reason to implement SUBLIST this way is, of course, the > bane of indentation syntax, LET: > > let > !!$ x $ compute 'x > !!!!y $ compute 'y > !!use x y > ==> > let > ; the first indent below is the "real" indent > INDENT INDENT INDENT x INDENT compute 'x > ; at this point, stack is (0 2 ? ?) > ; again, first indent below is "real" indent" > INDENT y INDENT compute 'y > ; at this point, stack is (0 2 ? ? 4 ?) > ; since we get back to an indent of 2, > ; emit 2 DEDENT's to get past the 4, > ; then (via rule 5.1) pop off all ? to > ; reach the 2 (which involves popping > ; off 4 indents). > DEDENT DEDENT DEDENT DEDENT use x y > ; again, empty line, pop off the single dedent > DEDENT > ==> > let > !\\ > !!\\ > !!!x > !!!!compute 'x > !!!!!y > !!!!!!compute 'y > ..... > > well, bummer, doesn't work. > > Oh well. > > Sincerely, > AmkG > > >> >> A common objection to any scheme allowing unmatched dedents is that it >> requires lookahead, both for machine parsing *and humans*. When you >> read: >> >> foo >> ! ! bar >> ... pages of stuff >> ! ! baz >> ! quux >> >> it's very disconcerting to realize that all this bar...baz stuff was not >> a >> direct child of foo but was nested within a ...quux construct! >> But in our case, $ already declares that we opened an inner construct, so >> I >> think it won't be surprising to humans. >> >> What about multiple $ ambiguity? Given: >> >> A1 $ B1 $ C1 >> ! ! C2 >> ! B2 >> >> why does the dedent return you to the inner B level and not the outer A >> level? >> It's the only sane choice, for several reasons: >> - Continuity with current usage, which I expect will remain the dominant >> use of $: without unmatched dedents you only have access to innermost C >> level, so the accessible level should be the next innermost. >> - It's the only way (without magic lookahead) that allows you to access >> all >> levels, if desired. >> - It's similar to the standard resolution of "if A1 if B1 if C1 else C2 >> else B2". >> > ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_feb _______________________________________________ Readable-discuss mailing list Readable-discuss@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/readable-discuss