-- (C) Copyright International Business Machines Corporation 23 January 
-- 1990.  All Rights Reserved. 
--  
-- See the file USERAGREEMENT distributed with this software for full 
-- terms and conditions of use. 
-- File: cgevery.pp
-- Author: Andy Lowry
-- SCCS Info: @(#)cgevery.pp	1.12 3/13/90

-- This process generates code for an EVERY OF operation.  The code is
-- based on a 'allOrNone' loop skeleton produced by cgSelector.  Prior
-- to the loop, the destination table is initialized via 'new_table'.
-- In the body of the loop, a matching table element is copied and
-- then inserted into the destination table.


-- A 'scan' style loop ends up looking like this:
--
--	new 		t1
-- 	initget 	r,t
-- loop:get_or_goto 	r,t {endloop}
--	[additional tests, result in 'test']
--	bfalse 		test {loop}
--      copy 		tmp,r
--	insert 		t1,tmp
--	branch 		{loop}
-- endloop:
--	endget		r,t
--

#include "typemark.h"
#include "codegen.h"

cgEvery: using (cgInternal, interpform)

process (Q: cgStmtQ)

declare
  args: cgStmt;
  dst: objectname;		-- table to be created
  dstTdef: type_definition;	-- its type
  dstAddr: interpform!operand;	-- its LI address
  tbl: objectname;		-- source table
  tblAddr: interpform!operand;	-- its LI address
  endLoop: cgSelectorContinueFn; -- call this to tie off the loop
  empty: empty;

begin
  receive args from Q;
  reveal args.stmt.qualifier.selector;

  -- get the destination table and its type and LI address
  dst := objectname#(AREF(tmp,args.stmt.operands,ZERO));
  dstAddr <- interpform!operand#(args.cgData.Proc.objAddr(dst));
  dstTdef <- type_definition#(FNS.typeDef(
      typename#(args.cgData.Proc.objType(dst))));
  reveal dstTdef.specification.table_info;

  -- Generate a 'new_table' instruction for the destination table
  block declare
    op: interpform!operation;
  begin
    new op;
    op.opcode <- interpform!opcode#'new_table';
    new op.operands;
    insert interpform!operand#(copy of dstAddr) into op.operands;
    unite op.qualifier.new_table from new_table_info#(
	FNS.newTableInfo(dstTdef.specification.table_info,
		         FNS.typeDef,FNS.compOffsets));
    ADDINSTR(op);
  end block;

  -- Get the LI address of the source table
  tbl <- objectname#(AREF(tmp,args.stmt.operands,ONE));
  tblAddr <- interpform!operand#(args.cgData.Proc.objAddr(tbl));

  -- Now generate the top part of the loop skeleton
  block declare
    lk: lookupInfo;		-- need a placeholder for the call
  begin
    endLoop <- cgSelectorContinueFn#(FNS.cgSelector(
        args.stmt.qualifier.selector, args.cgData,
	typename#(args.cgData.Proc.objType(tbl)),
	selectorLoopType#'allOrNone', lk, tblAddr));
  end block;

  -- Now generate the loop body, which needs to copy the
  -- representative element and then insert it into the destination
  -- table
  block declare
    tmpAddr: interpform!operand;
    eltAddr: interpform!operand;
    op: interpform!operation;
  begin
    tmpAddr <- interpform!operand#(args.cgData.Proc.tmpAddr());
    eltAddr <- interpform!operand#(args.cgData.Proc.rootAddr(
	args.stmt.qualifier.selector.element, 
	args.stmt.qualifier.selector.scope));

    -- First the 'copy' instruction
    new op;
    op.opcode <- interpform!opcode#'copy';
    new op.operands;
    insert interpform!operand#(copy of tmpAddr) into op.operands;
    insert eltAddr into op.operands;
    unite op.qualifier.empty from empty;
    ADDINSTR(op);

    -- Now the 'insert' instruction
    new op;
    op.opcode <- interpform!opcode#'insert';
    new op.operands;
    insert dstAddr into op.operands;
    insert tmpAddr into op.operands;
    unite op.qualifier.empty from empty;
    ADDINSTR(op);

  end block;

  -- Now finish up the loop skeleton
  call endLoop(args.cgData);

  return args;

end process
