
% Inject index mappings into template dimension space.

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

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

% ``meta-syntax'' is
%
%  <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>), List(<exp_handle>), <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 mapping descriptors
%
%
%  <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>


idxMapInjectExpressionHandleList([], _, _).
idxMapInjectExpressionHandleList([EH | EHs], Syms, Strategy) :-
    idxMapInjectExpressionHandle(EH, Syms, Strategy),
    idxMapInjectExpressionHandleList(EHs, Syms, Strategy).

idxMapInjectExpressionHandle(EH, Syms, Strategy) :-
    symLookUp(EH, expression(E, Atr), Syms),
    idxMapInjectExpression(E, Atr, Syms, Strategy).

idxMapInjectExpression(varRef(_), Atr, Syms, Strategy) :-
    expAtr(Atr),
      CtxMap := Atr -> ctxMap,  LocMap := Atr -> locMap,
    idxMapInject(CtxMap, Syms, Strategy),
    idxMapInject(LocMap, Syms, Strategy).
idxMapInjectExpression(funRef(_, _, _), Atr, Syms, Strategy) :-
    expAtr(Atr),
      EHs    := Atr -> mapDaughts,
      CtxMap := Atr -> ctxMap,  LocMap := Atr -> locMap,
    idxMapInject(CtxMap, Syms, Strategy),
    idxMapInject(LocMap, Syms, Strategy),
    idxMapInjectExpressionHandleList(EHs, Syms, Strategy).
idxMapInjectExpression(subscript(_, _), Atr, Syms, Strategy) :-
    expAtr(Atr),
      EHs    := Atr -> mapDaughts,
      CtxMap := Atr -> ctxMap,      LocMap := Atr -> locMap,
    idxMapInject(CtxMap, Syms, Strategy),
    idxMapInject(LocMap, Syms, Strategy),
    idxMapInjectExpressionHandleList(EHs, Syms, Strategy).
idxMapInjectExpression(forall(_, Shape, _, EHs), _, Syms, Strategy) :-
    idxMapInjectExpressionHandleList(Shape, Syms, Strategy),
    idxMapInjectExpressionHandleList(EH, Syms, Strategy).
idxMapInjectExpression(arrall(_, Shape, EH), _, Syms, Strategy) :-
    idxMapInjectExpressionHandleList(Shape, Syms, Strategy),
    idxMapInjectExpressionHandleList(EH, Syms, Strategy).
idxMapInjectExpression(idxRef(SizeH, IH), Atr, Syms, Strategy) :-
    idxMapInjectExpressionHandle(SizeH, Syms, Strategy).
idxMapInjectExpression(size(_, EH), Atr, Syms, Strategy) :-
    expAtr(Atr),
      CtxMap := Atr -> ctxMap,      LocMap := Atr -> locMap,
    idxMapInject(CtxMap, Syms, Strategy),
    idxMapInject(LocMap, Syms, Strategy),
    idxMapInjectExpressionHandle(SizeH, Syms, Strategy).
idxMapInjectExpression(expRef(_), _, _, Strategy).
idxMapInjectExpression(E, _, _, Strategy) :- isLiteral(E).

% ----- `idxMapInject' -----

idxMapInject(Map, Syms, Strategy) :-
    getTemplate(T, Map),
    ground(T),
    getDimSpace(Rank, Dims, T, Syms),
    getAIMap(AIMap, Map),
    getIMap(IdxMap, Map),
    doInject(AIMap, IdxMap, Rank, Dims, Strategy).


doInject(AIMap, IdxMap, Rank, Dims, CRank) :-
    Rank < CRank,
    injectAIMap(AIMap, DimsRest, Dims),
    injectIMap(AIMap, _, Dims).
doInject(AIMap, IdxMap, Rank, Dims, CRank) :-
    Rank >= CRank,
    injectOrCollapseAIMap(AIMap, DimsRest, Dims),
    injectOrCollapseIMap(AIMap, _, Dims).


injectOrCollapseAIMap([], Dims, Dims).
injectOrCollapseAIMap([_ :: D | AIMappings], DimsRest, Dims),
    removeMember(D, Dims, DimsRemaining),
    injectOrCollapseAIMap(AIMappings, DimsRest, DimsRemaining).
injectOrCollapseAIMap([_ :: col | AIMappings], DimsRest, Dims),
    injectOrCollapseAIMap(AIMappings, DimsRest, Dims).

injectOrCollapseIMap([], Dims, Dims).
injectOrCollapseIMap([_ :: _ -> D | AIMappings], DimsRest, Dims),
    removeMember(D, Dims, DimsRemaining),
    injectOrCollapseIMap(AIMappings, DimsRest, DimsRemaining).
injectOrCollapseIMap([_ :: _ -> col | AIMappings], DimsRest, Dims),
    injectOrCollapseIMap(AIMappings, DimsRest, Dims).


% `inject' predicates differ from `injectOrCollapse' ones in that they
% never *instantiate* a collapsed mapping, although they will accept a
% previously instantiated collapsed mapping.

injectAIMap([], Dims, Dims).
injectAIMap([_ :: D | AIMappings], DimsRest, Dims),
    removeMember(D, Dims, DimsRemaining),
    injectAIMap(AIMappings, DimsRest, DimsRemaining).
injectAIMap([_ :: D | AIMappings], DimsRest, Dims),
    ground(D),
    D = col,
    injectAIMap(AIMappings, DimsRest, Dims).

injectIMap([], Dims, Dims).
injectIMap([_ :: _ -> D | AIMappings], DimsRest, Dims),
    removeMember(D, Dims, DimsRemaining),
    injectIMap(AIMappings, DimsRest, DimsRemaining).
injectIMap([_ :: _ -> D | AIMappings], DimsRest, Dims),
    ground(D),
    D = col,
    injectIMap(AIMappings, DimsRest, Dims).


getDimSpace(0, [], def, _).
getDimSpace(Rank, Dims, variable(VH), Syms) :-
    symLookUp(VH, variable(VAtr), Syms),
    varAtr(VAtr),
      Shape := VAtr -> shape,
    size(Shape, Rank),
    enum(Rank, Dims).

