

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

% Node is:
%   fun(F, I, D, A)
%   arr(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).

printAssocs(In, for(I, D)) :-
    tab(In),
    printString("for "),
    writeList(I),
    nl,
    Inpp is In + 2,
    printDaughtAssocs(Inpp, D).
printAssocs(In, idx(X, _)) :-
    tab(In),
    printString("idx "),
    write(X),
    nl.
printAssocs(In, fun(F, I, D, A, B)) :-
    tab(In),
    printString("fun "),
    write(F),
    printString(" "),
    writeList(I),
    printAssoc(A, B),
    nl,
    Inpp is In + 2,
    printDaughtAssocs(Inpp, D).
printAssocs(In, var(V, D, A, B)) :-
    tab(In),
    printString("var "),
    write(V),
    printAssoc(A, B),
    nl,
    Inpp is In + 2,
    printDaughtAssocs(Inpp, D).
printAssocs(In, arr(I, D, _, _)) :-
    tab(In),
    printString("arr "),
    writeList(I),
    nl,
    Inpp is In + 2,
    printDaughtAssocs(Inpp, D).

printDaughtAssocs(_, []) :- !.
printDaughtAssocs(In, [X | L]) :- printAssocs(In, X), printDaughtAssocs(In, L).

% Print node and target alignments

printAssoc(A, B) :-
    current_output(Op),
    line_position(Op, P),
    S is 30 - P,
    tab(S),
    printAlign(A),
    line_position(Op, Q),
    T is 55 - Q,
    tab(T),
    printAlign(B).

printAlign(align(ran(V, _), M)) :-
    write(V),
    printString(":"),
    write(M).

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

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

