

% ?- op(700, xfx, ->).

% Node is:                     **** No it isn't, any more!! ****
%   fun(F, I, D, A)
%   arg(I, D, A, A)
%   var(V, D, A, A)
%   idx(X, A)
% where
%   D is a list of nodes (excluding `for' nodes).
%   A is a target or full association map.
%   F is a function
%   I is list of indices.
%   V is a variable.
%   X is an index.

% Association map is:
%   align(V, M)
% where
%   V is a variable.
%   M is a list of mappings.

% Mapping is:
%   X -> D
% where
%   X is an index.
%   D is a dimension (integer).

printNodArc(In, nod(Ds, _, A, _)) :-
    tab(In),
    printString("nod "),
    print1Assoc(A),
    nl,
    Inpp is In + 2,
    printDaughtNodArc(Inpp, Ds).
printNodArc(In, arg(I, D, _, A, _)) :-
    tab(In),
    printString("arg "),
    writeList(I),
    print1Assoc(A),
    nl,
    Inpp is In + 2,
    printNodArc(Inpp, D).
printNodArc(In, arc(D, _, A, B)) :-
    tab(In),
    printString("arc "),
    print2Assoc(A, B),
    nl,
    Inpp is In + 2,
    printNodArc(Inpp, D).
printNodArc(In, var(V, _, _, A)) :-
    tab(In),
    printString("var "),
    write(V),
    print1Assoc(A),
    nl.
printNodArc(In, fun(F, I)) :-
    tab(In),
    printString("fun "),
    write(F),
    printString(" "),
    writeList(I),
    nl.
printNodArc(In, idx(X)) :-
    tab(In),
    printString("idx "),
    write(X),
    nl.

printDaughtNodArc(_, []) :- !.
printDaughtNodArc(In, [X | L]) :- printNodArc(In, X), printDaughtNodArc(In, L).

%-------

printIdxMap(In, idx(X)) :-
    tab(In),
    printString("idx "),
    write(X),
    nl.
%printIdxMap(In, fun(F, I, Ds, A, B)) :-
printIdxMap(In, fun(F, I, Ds, A)) :-
    tab(In),
    printString("fun "),
    write(F),
    printString(" "),
    writeList(I),
    %print2Assoc(A, B),
    print1Assoc(A),
    nl,
    Inpp is In + 2,
    printDaughtIdxMap(Inpp, Ds).
printIdxMap(In, var(V, Ds, A)) :-
    tab(In),
    printString("var "),
    write(V),
    print1Assoc(A),
    nl,
    Inpp is In + 2,
    printDaughtIdxMap(Inpp, Ds).
printIdxMap(In, arg(I, D, A)) :-
    tab(In),
    printString("arg "),
    writeList(I),
    print1Assoc(A),
    nl,
    Inpp is In + 2,
    printIdxMap(Inpp, D).

printDaughtIdxMap(_, []) :- !.
printDaughtIdxMap(In, [X | L]) :- printIdxMap(In, X), printDaughtIdxMap(In, L).

% Print node and target alignments

print1Assoc(A) :-
    current_output(Op),
    line_position(Op, P),
    S is 35 - P,
    tab(S),
    printAlign(A).

print2Assoc(A, B) :-
    current_output(Op),
    line_position(Op, P),
    S is 35 - P,
    tab(S),
    printAlign(A),
    line_position(Op, Q),
    T is 60 - Q,
    tab(T),
    printAlign(B).

printAlign(map(T, M)) :-
    write(T),
    printString(":"),
    write(M).

% ---------------

% printEmbed(In, idx(X)) :-
%     tab(In),
%     printString("idx "),
%     write(X),
%     nl.
% printEmbed(In, fun(F, I, Ds, A)) :-
%     tab(In),
%     printString("fun "),
%     write(F),
%     printString(" "),
%     writeList(I),
%     print1Emb(A),
%     nl,
%     Inpp is In + 2,
%     printDaughtEmbed(Inpp, Ds).
% printEmbed(In, var(V, Ds, A)) :-
%     tab(In),
%     printString("var "),
%     write(V),
%     print1Emb(A),
%     nl,
%     Inpp is In + 2,
%     printDaughtEmbed(Inpp, Ds).
% printEmbed(In, arg(I, D, A)) :-
%     tab(In),
%     printString("arg "),
%     writeList(I),
%     print1Emb(A),
%     nl,
%     Inpp is In + 2,
%     printEmbed(Inpp, D).

printEmbed(In, idx(X)) :-
    tab(In),
    printString("idx "),
    write(X),
    nl.
printEmbed(In, fun(F, I, Ds, Xs, T, P, U, Q)) :-
    tab(In),
    printString("fun "),
    write(F),
    printString(" "),
    writeList(I),
    printEmbs(Xs, T, P, U, Q),
    nl,
    Inpp is In + 2,
    printDaughtEmbed(Inpp, Ds).
printEmbed(In, var(V, Ds, Xs, T, P, U, Q)) :-
    tab(In),
    printString("var "),
    write(V),
    printEmbs(Xs, T, P, U, Q),
    nl,
    Inpp is In + 2,
    printDaughtEmbed(Inpp, Ds).
printEmbed(In, arg(I, D)) :-
    tab(In),
    printString("arg "),
    writeList(I),
    nl,
    Inpp is In + 2,
    printEmbed(Inpp, D).

printDaughtEmbed(_, []) :- !.
printDaughtEmbed(In, [X | L]) :- printEmbed(In, X), printDaughtEmbed(In, L).

print1Emb(A) :-
    current_output(Op),
    line_position(Op, P),
    S is 35 - P,
    tab(S),
    printEmb(A).

print2Emb(A, B) :-
    current_output(Op),
    line_position(Op, P),
    S is 40 - P,
    tab(S),
    printEmb(A),
    line_position(Op, Q),
    T is 70 - Q,
    tab(T),
    printEmb(B).

printEmbs(Xs, T, P, U, Q) :-
    current_output(Op),
    line_position(Op, Pos1),
    S1 is 40 - Pos1,
    tab(S1),
    write(Xs),
    line_position(Op, Pos2),
    S2 is 50 - Pos2,
    tab(S2),
    printEmb(T, P),
    line_position(Op, Pos3),
    S3 is 65 - Pos3,
    tab(S3),
    printEmb(U, Q).

printEmb(T, P) :-
    write(T),
    printString(":"),
    write(P).

% ---------------

writeList([])      :- !.
writeList([X])     :- write(X), !.
writeList([X | L]) :- write(X), printString(", "), writeList(L).

printString([]) :- !.
printString([X | T]) :- put(X), printString(T).

