~eshel/eshellisp

df2144d5403b0383aeea8353b6c06d7fa478e88f — Eshel Yaron 2 years ago d6d7671
ADDED: dotted pair notation and general support for improper lists
3 files changed, 95 insertions(+), 38 deletions(-)

M prolog/eshellisp/read.pl
M prolog/eshellisp/write.pl
M test/suite.scm
M prolog/eshellisp/read.pl => prolog/eshellisp/read.pl +77 -25
@@ 37,18 37,40 @@ tokens([]) --> [].
token('(')  --> [40], !.
token(')')  --> [41], !.
token('\'') --> [39], !.
token('.')  --> [46], !.
token(number(Number, Len)) -->
    digits([H|T]),
    !,
    { length([H|T], Len), number_codes(Number, [H|T]) }.
token(symbol(Name)) -->
    string_without([10, 32, 39, 40, 41], [H|T]),
    string_without([10, 32, 39, 40, 41, 46], [H|T]),
    !,
    { atom_codes(Name, [H|T]) }.
token(nl) --> [10], !.
token(ws) --> [32], !.


:- det(ws//2).
ws(position(L0, C0, O0), position(L, C, O)) -->
    [ws],
    !,
    { C1 is C0 + 1,
      O1 is O0 + 1
    },
    ws(position(L0, C1, O1), position(L, C, O)).
ws(position(L0, _, O0), position(L, C, O)) -->
    [nl],
    !,
    { L1 is L0 + 1,
      O1 is O0 + 1
    },
    ws(position(L1, 0, O1), position(L, C, O)).
ws(P, P) --> !.



:- det(form_components/3).

form(symbol(Name),
     position(StartLine, StartColumn, StartOffset),
     position(StartLine, EndColumn, EndOffset)) -->


@@ 66,21 88,26 @@ form(number(Number),
    { EndColumn is StartColumn + Length,
      EndOffset is StartOffset + Length
    }.
form(list(List),
form(list(Cons),
     position(StartLine, StartColumn, StartOffset),
     position(EndLine, EndColumn, EndOffset)) -->
    ['('],
    !,
    { C is StartColumn + 1,
      O is StartOffset + 1
    { C0 is StartColumn + 1,
      O0 is StartOffset + 1
    },
    forms(List, position(StartLine, C, O), position(L1, C1, O1)),
    [')'],
    !,
    { EndLine is L1,
      EndColumn is C1 + 1,
      EndOffset is O1 + 1
    }.
    ws(position(StartLine, C0, O0), position(L1, C1, O1)),
    (   [')']
    ->  {   Cons = [],
            EndLine is L1,
            EndColumn is C1 + 1,
            EndOffset is O1 + 1
        }
    ;   {   Cons = [form(Car, position(L1, C1, O1), PCar)|Cdr]   },
        form(Car, position(L1, C1, O1),  PCar),
        ws(PCar, PCdr),
        cdr(Cdr, PCdr,  position(EndLine, EndColumn, EndOffset))
    ).
form(quote(form(Exp, position(StartLine, C, O), position(EndLine, EndColumn, EndOffset))),
     position(StartLine, StartColumn, StartOffset),
     position(EndLine, EndColumn, EndOffset)) -->


@@ 92,25 119,42 @@ form(quote(form(Exp, position(StartLine, C, O), position(EndLine, EndColumn, End
    form(Exp, position(StartLine, C, O), position(EndLine, EndColumn, EndOffset)).


forms(List, position(L0, C0, O0), position(L, C, O)) -->
    [ws],
cdr([], position(L, C0, O0), position(L, C, O)) -->
    [')'],
    !,
    { C1 is C0 + 1,
      O1 is O0 + 1
    },
    forms(List, position(L0, C1, O1), position(L, C, O)).
forms(List, position(L0, _C0, O0), position(L, C, O)) -->
    [nl],
    {   C is C0 + 1,
        O is O0 + 1
    }.
cdr(form(Cdr, P0, P), position(L0, C0, O0), position(L, C, O)) -->
    ['.'],
    !,
    { L1 is L0 + 1,
      O1 is O0 + 1
    {   C1 is C0 + 1,
        O1 is O0 + 1
    },
    forms(List, position(L1, 0, O1), position(L, C, O)).
forms([form(H, P0, P1)|T], P0, P) -->
    ws(position(L0, C1, O1), P0),
    form(Cdr, P0, P),
    ws(P, position(L, C4, O4)),
    [')'],
    {   C is C4 + 1,
        O is O4 + 1
    }.
cdr([form(Car, P0, P)|Cdr], P0, P) -->
    form(Car, P0, P1),
    ws(P1, P2),
    cdr(Cdr, P2, P).


forms(Forms, P0, P) -->
    ws(P0, P1),
    !,
    forms_(Forms, P1, P).


forms_([form(H, P0, P1)|T], P0, P) -->
    form(H, P0, P1),
    !,
    forms(T, P1, P).
forms([], P, P) --> [].
forms_([], P, P) --> [].


form_components(form(Form, Start, End), Expression, layout(Start, End, Children)) :-


@@ 119,9 163,17 @@ form_components(form(Form, Start, End), Expression, layout(Start, End, Children)

form_components_(list(List), Expressions, Children) :-
    !,
    maplist(form_components, List, Expressions, Children).
    forms_components(List, Expressions, Children).
form_components_(quote(Quoted), quote(Expression), [Layout]) :-
    !,
    form_components(Quoted, Expression, Layout).
form_components_(symbol(Symbol), Symbol, []) :- !.
form_components_(number(Number), Number, []) :- !.

forms_components([H|T], [HE|TE], [HL|TL]) :-
    !,
    form_components(H, HE, HL),
    forms_components(T, TE, TL).
forms_components([], [], []) :- !.
forms_components(Form, Expression, Layout) :-
    form_components(Form, Expression, Layout).

M prolog/eshellisp/write.pl => prolog/eshellisp/write.pl +16 -13
@@ 27,21 27,24 @@ form(Number) -->
    { number(Number) },
    !,
    [ '~w'-[Number] ].
form(List) -->
    { is_list(List) },
form([]) -->
    !,
    [ '()'-[] ].
form([Car|Cdr]) -->
    !,
    [ '('-[] ],
    forms(List),
    [ ')'-[] ].
    form(Car),
    cdr(Cdr).

forms([A,B|T]) -->
    !,
    form(A),
    [ ' '-[] ],
    forms([B|T]).
forms([H]) -->
cdr([]) -->
    !,
    form(H).
forms([]) -->
    [ ')'-[] ].
cdr([Car|Cdr]) -->
    !,
    [].
    [ ' '-[] ],
    form(Car),
    cdr(Cdr).
cdr(Form) -->
    [ ' . '-[] ],
    form(Form),
    [ ')'-[] ].

M test/suite.scm => test/suite.scm +2 -0
@@ 7,3 7,5 @@
(test '(not 3) (not 3) #f)
(test '(boolean=? #t #t) (boolean=? #t #t) #t)
(test '(boolean=? #t #t) (boolean=? #t #f) #f)
(test 'dotted-proper-list '(a . (b . (c . (d . ())))) '(a b c d))
(test 'dotted-non-proper-list '(a b c . d) '(a . (b . (c . d))))