-- (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: cgexists.pp
-- Author: Andy Lowry
-- SCCS Info: @(#)cgexists.pp	1.9 3/13/90

-- This process generates code for an EXISTS OF operation.  The code
-- is based on a 'oneOrNone' loop skeleton produced by cgSelector.
-- Prior to the loop, the result is initialized to 'false'.  In the
-- body of the loop, a matching entry causes the result to be changed
-- to 'true'.

-- A 'scan' style loop ends up looking like this:
--
--	boolean		result {'false'}
-- 	initget 	r,t
-- loop:get_or_goto 	r,t {endloop}
--	[additional tests, result in 'test']
--	bfalse 		test {loop}
--      boolean		result {'true'}
-- endloop:
--	endget		r,t
--

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

cgExists: using (cgInternal, interpform)

process (Q: cgStmtQ)

declare
  args: cgStmt;
  dstAddr: interpform!operand;	-- result LI address
  tbl: objectname;		-- source table
  tblAddr: interpform!operand;	-- its LI address
  endLoop: cgSelectorContinueFn; -- call this to tie off the loop

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

  -- get the destination address
  dstAddr <- interpform!operand#(args.cgData.Proc.objAddr(
      objectname#(AREF(tmp,args.stmt.operands,ZERO))));

  -- Initialize the destination to 'false' before the loop
  block declare
    op: interpform!operation;
  begin
    op := args.cgData.Tplt.boolF;
    insert interpform!operand#(copy of dstAddr) into op.operands;
    ADDINSTR(op);
  end block;

  -- get the source table address
  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;		-- placeholder for the call
  begin
    endLoop <- cgSelectorContinueFn#(FNS.cgSelector(
        args.stmt.qualifier.selector, args.cgData,
	typename#(args.cgData.Proc.objType(tbl)),
	selectorLoopType#'oneOrNone', lk, tblAddr));
  end block;

  -- Now generate the loop body, which changes the result to 'true'
  -- when a matching element is found
  block declare
    op: interpform!operation;
  begin
    op := args.cgData.Tplt.boolT;
    insert dstAddr into op.operands;
    ADDINSTR(op);
  end block;

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

  return args;

end process
