
% Apply domain mapper to program.

% ---------------------------------------------------------------------
 
% $Id$
 
% $Log$

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

% ``meta-syntax'' is
%
%  <sym_tab>     ::= Table(<declaration>)
%
%  <declaration> ::=
%    variable(<var_attr>)                  |
%    function(<fun_attr>)                  |
%    expression(<expression>, <exp_attr>)
%
%
%  <expression>  ::=
%    expRef(<exp_handle>)                                            |
%    idxRef(<exp_handle>, <idx_handle>)                              |
%    varRef(<var_handle>)                                            |
%    funRef(<fun_handle>, <tag>, List(<exp_handle>))                 |
%    subscript(<exp_handle>, List(<exp_handle>))                     |
%    arrall(List(<idx_handle>), <idx_tab>, <exp_handle>)             |
%    forall(List(<idx_handle>), List(<exp_handle>), List(<exp_handle>),
%           List(<exp_handle>))                                      |
%    size(<literal>, <exp_handle>)                                   |
%    literal(<literal>)                                              |
%    true                                                            |
%    false                                                           |
%    any
%
%  <index_declaration> ::= index(<range>, <idx_attr>)
%
%  <tag>         ::= <predef> | user
%
%  <predef>      ::= ...

% Attribute meta-syntax...
%
%  <fun_attr> ::= syms         :: <sym_tab>               #
%                 declarations :: List(<var_handle> |
%                                      <fun_handle> |
%                                      <exp_handle>)      #
%                 statements   :: List(<exp_handle>)      #
%                 dummies      :: List(<var_handle>)      #
%                 result       :: <var_handle>            #
%                 class        :: elemental | array       #
%                 dumShps      :: List(<extern_shape>)    #
%                 resShp       :: <extern_shape>          #
%                 dumMaps      :: List(<extern_mapping>)  #
%                 resMap       :: <extern_mapping>        #
%                 dumAlnGrps   :: List(List(<literal>))   #
%                 resAlnGrp    :: List(<literal>)
%
%  <var_attr> ::= shape    :: List(<exp_handle>)         #
%                 ishape   :: List(<exp_handle>)         #
%                 mapDesc  :: <var_mapping_desc>         #
%                 imapDesc :: <var_mapping_desc>
%
%  <exp_attr> ::= shape :: List(<range>)

% Syntax of external expressions...
%
%  <extern_shape> ::= List(<external>)
%
%  <external> ::= literal(<literal>)                            |
%                 varRef(<var_handle>)                          |
%                 funRef(<fun_handle>, <tag>, List(<external>)) |
%                 size(<literal>, <var_handle>)                 |
%                 arg(<literal>)                                |
%                 sizeArg(<literal>, <literal>)                 |
%                 any

% Syntax of mapping descriptors
%
%
%  <var_mapping_desc>  ::=  distribute                   |
%                           align(<template>,
%                                 List(<arr_idx_mapping_desc),
%                                 List(<embedding_desc>))
%
%  <exp_mapping_desc>  ::=  align(<template>,
%                                 List(<arr_idx_mapping_desc),
%                                 List(<idx_mapping_desc),
%                                 List(<embedding_desc>))
%
%  <arr_idx_mapping_desc>  ::=  <map> :: <dimension>
%
%  <template>          ::= def | <var_handle>
%
%  <idx_mapping_desc>  ::= <map> :: <idx_handle> -> <dimension>
%
%  <map>               ::= map(<exp_handle>, <exp_handle>)  |
%                          id                               |
%                          any
%
%  <embedding_desc>    ::=  emb(<exp_handle>) :: <dimension>  |
%                           rep :: <dimension>
%
%  <extern_mapping>    ::=  any                          |
%                           align(<extern_template>,
%                                 List(<extern_idx_mapping>),
%                                 List(<extern_embedding>))
%
%  <extern_template>     ::=  global(<var_handle>) |
%                             arg(<literal>)       |
%                             def
%
%  <extern_idx_mapping>  ::=  <extern_map> :: <dimension>
%
%  <extern_map>          ::=  map(<external>, <external>)  |
%                             id                           |
%                             any
%
%  <extern_embedding>  ::=  emb(<external>) :: <dimension> |
%                           rep :: <dimension>
%
%  <dimension>         ::=  <literal>  |  col


map(DHs, Syms) :- mapProgram(DHs, [], Syms).


mapProgram(DHs, SHs, Syms) :-
    mapDeclarationList(DHs, Syms),
    mapExpressionHandles(SHs, Syms, _).


mapDeclarationList([], _).
mapDeclarationList([DH | DHs], Syms) :-
    symLookUp(DH, D, Syms),
    mapDeclaration(D, Syms),
    mapDeclarationList(DHs, Syms).

mapDeclaration(function(Atr), _) :-
    funAtr(Atr),
      Syms := Atr -> syms,
      DHs  := Atr -> declarations, SHs  := Atr -> statements,
    mapProgram(DHs, SHs, Syms).
mapDeclaration(variable(Atr), Syms) :-
    varAtr(Atr),
      Shape   := Atr -> ishape,
      MapDesc := Atr -> mapDesc,
    mapExpressionHandles(Shape, Syms),
    mapMapDesc(MapDesc, Syms).
mapDeclaration(expression(E, Atr), Syms) :-
    mapExpression(E, Atr, Syms).


mapExpressionHandles([], _).
mapExpressionHandles([EH | EHs], Syms) :-
    mapExpressionHandle(EH, Syms),
    mapDomain([EH], Syms),
    mapExpressionHandles(EHs, Syms).

mapExpressionHandleList([], _).
mapExpressionHandleList([EH | EHs], Syms) :-
    mapExpressionHandle(EH, Syms),
    mapExpressionHandleList(EHs, Syms).

mapExpressionHandle(EH, Syms) :-
    symLookUp(EH, expression(E, Atr), Syms),
    mapExpression(E, Atr, Syms).

mapExpression(varRef(_), _).
mapExpression(funRef(_, _, EHs), Atr, Syms) :-
    expAtr(Atr),
      MapDomains := Atr -> mapDomains,
    mapExpressionHandleList(EHs, Syms),
    mapDomains(MapDomains, Syms).
mapExpression(subscript(EH, EHs), Atr, Syms) :-
    expAtr(Atr),
      MapDomains := Atr -> mapDomains,
    mapExpressionHandle(EH, Syms),
    mapExpressionHandleList(EHs, Syms),
    mapDomains(MapDomains, Syms).
mapExpression(forall(_, Shape, _, EHs), _, Syms) :-
    mapExpressionHandleList(Shape, Syms),
    mapExpressionHandleList(EH, Syms).
mapExpression(arrall(_, Shape, EH), _, Syms) :-
    mapExpressionHandleList(Shape, Syms),
    mapExpressionHandleList(EH, Syms).
mapExpression(idxRef(SizeH, IH), Atr, Syms) :-
    mapExpressionHandle(SizeH, Syms).
mapExpression(size(_, EH), Atr, Syms) :-
    mapExpressionHandle(EH, Syms).
mapExpression(expRef(_), _, _).
mapExpression(E, _, _) :- isLiteral(E).


mapMapDesc(distribute, _).
mapMapDesc(align(T, AIMap, Embeds), Syms) :-
    mapAIMappings(AIMap, Syms),
    mapEmbeddings(Embeds).

mapAIMappings([], _).
mapAIMappings([AIMapping | AIMappings], Syms) :-
    mapAIMapping(AIMapping, Syms),
    mapAIMappings(AIMappings, Syms).

mapAIMapping(M :: _, Syms) :-
    mapLin(M, Syms).

mapLin(map(MH, CH), Syms) :-
    mapExpressionHandle(MH, Syms, _),
    mapExpressionHandle(CH, Syms, _).
mapLin(id,  _).
mapLin(any, _).

mapEmbeddings([], _).
mapEmbeddings([Embed | Embeds], Syms) :-
    mapEmbedding(Embed, Syms),
    mapEmbeddings(Embeds, Syms).

mapEmbedding(emb(EH) :: _, Syms) :-
    mapExpressionHandle(EH, Syms, _).
mapEmbedding(rep :: _, _).


% ----- Domain mapper -----

mapDomains([], Syms).
mapDomains([MapDomain | MapDomains], Syms) :-
    mapDomain(MapDomain, Syms),
    mapDomains(MapDomains, Syms).

mapDomain(EHs, Syms) :-
    domainCRank(CRank, EHs, Syms),
    idxMapSubsExpressionHandleList(EHs, Syms),
    idxMapInjectExpressionHandleList(EHs, Syms, CRank),
    !,
    idxMapSynthDimsExpressionHandleList(EHs, Syms),
    mapSurjectExpressionHandleList(EHs, Syms),
    embedSubsExpressionHandleList(EHs, Syms),
    replicateExpressionHandleList(EHs, Syms),
    resolveMapsExpressionHandleList(EHs, Syms).
mapDomain(EHs, Syms) :-
    defaultMaps(EHs, Syms).

