-- (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: cgclause.pp
-- Author: Andy Lowry
-- SCCS Info: @(#)cgclause.pp	1.14 2/15/92

-- This function performs initial code generation for a single clause.
-- Code is generated into the current basic block as given by
-- cgData.Proc.BBData.curBB, though by the time this clause is
-- finished, there may be several new basic blocks, and the current BB
-- may have changed.

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

cgClause: using (cgInternal, positions, posmap, common, annotate)

process (Q: cgClauseQ)

declare
  args: cgClause;
  pos: Aposition;
  prags: annotations;
begin
  receive args from Q;

  new pos;
  pos.clause := args.clauseid;

  -- cgstmt will always figure out the pragmas... following just
  -- creates a dummy empty pragma table to satisfy the interface
  new prags;

  block begin
    -- Translate any pre-clause coercions that may be needed
    block begin
      inspect hc in args.cgData.Proc.coercions.handlerCoercions[args.clauseid]
      begin
	for stmt in hc.coercions[] inspect
	  pos.statement := stmt.id;
	  call FNS.cgStmt(stmt,prags,args.cgData);
	end for;
      end inspect;
    on (NotFound)
      -- No coercions prior to this clause
    end block;

    -- Locate the clause we're supposed to translate
    inspect clause in args.cgData.Proc.proc.executable_part.clauses
	  [args.clauseid] begin
      -- Now translate each statement in the clause in turn
      for stmt in clause.statements[] inspect
	pos.statement := stmt.id;
	-- Translate pre-coercion statements
	block begin
	  inspect sc in args.cgData.Proc.coercions.precoercions[pos] begin
	    for prestmt in sc.coercions[] inspect
	      pos.statement := prestmt.id;
	      call FNS.cgStmt(prestmt,prags,args.cgData);
	    end for;
	  end inspect;
	on (NotFound)
	  -- no coercions prior to this stmt
	end block;

	-- Now the statement itself
	pos.statement := stmt.id;
	call FNS.cgStmt(stmt,prags,args.cgData);
	
	-- And finally post-coercions
	inspect scope in args.cgData.Proc.proc.executable_part.scopes
	      [args.cgData.Proc.proc.executable_part.main_scope]
	begin
	  if B(scope.clause <> args.clauseid) then
	    -- provided that this is not the main clause, for which
	    -- postcoercions are discarded to save some space and time,
	    -- since end_process does soft coercion of everything
	    -- that's 
	    -- left.
	    block begin
	      inspect sc in args.cgData.Proc.coercions.postcoercions[pos] 
	      begin
		for poststmt in sc.coercions[] inspect
		  pos.statement := poststmt.id;
		  call FNS.cgStmt(poststmt,prags,args.cgData);
		end for;
	      end inspect;
	    on (NotFound)
	      -- no coercions following this stmt
	    end block;
	  end if;
	end inspect;

      end for;
    end inspect;
  
  on (cgStmt.Discarded)
    block declare
      posmaps: position_Mappings;
      id: executable_id;
    begin
      print S("cgclause: Problem translating statement; file/line/column:");
      inspect x in args.cgData.Prog.annotations[S("Position Map")] begin
	unwrap posmaps from polymorph#(copy of x.thing) {init};
	unite id.pid from processid#(copy of args.cgData.Proc.proc.id);
	inspect map in posmaps[id] begin
	  inspect rec in map.mapping[pos] begin
	    print rec.cposition;
	  end inspect;
	end inspect;
      end inspect;
    end block;
  end block;
  
  return args;			-- all done
  
end process
