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

-- This module translates an INSPECT ... FROM polymorph {...}
-- statement.  The body of the statement is bracketed by an
-- 'inspect_poly' instruction and an 'endinspect_poly' instruction.
-- In both cases, the object introduced by the INSPECT statement is
-- the destination operand, and the source operand for the
-- 'inspect_poly' instruction is the polymorph object being inspected.
-- The formal typestate from the INSPECT statement is used to build
-- the 'inspect_poly' instruction qualifier.

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

cgInspPoly: using (cgInternal, interpform)

process (Q: cgStmtQ)
  
declare
  args: cgStmt;
  op: interpform!operation;
  dstAddr: interpform!operand;
  dstType: predefined!typename;
  empty: empty;
begin
  receive args from Q;
  reveal args.stmt.qualifier.inspect_polymorph;
  
  -- Get the LI address and type name for the inpsecting object
  block declare
    dst: predefined!objectname;
  begin
    -- Cons up a full objectname from the id's in the qualifier
    new dst;
    new dst.root;
    dst.root.root := args.stmt.qualifier.inspect_polymorph.element;
    dst.root.scope := args.stmt.qualifier.inspect_polymorph.scope;
    new dst.components;
    -- Get the address and type
    dstAddr <- interpform!operand#(args.cgData.Proc.objAddr(dst));
    dstType <- typename#(args.cgData.Proc.objType(dst));
  end block;
  
  -- Build up the 'inspect_poly' instruction
  new op;
  op.opcode <- interpform!opcode#'inspect_poly';
  new op.operands;
  insert interpform!operand#(copy of dstAddr) into op.operands;
  insert interpform!operand#(args.cgData.Proc.objAddr(
      objectname#(AREF(tmp,args.stmt.operands,ZERO)))) into op.operands;
  -- Build up the polymorph_info qualifier for the instruction
  block declare
    pi: interpform!polymorph_info;
  begin
    new pi;
    pi.type <- dstType;
    pi.typestate := args.stmt.qualifier.inspect_polymorph.typestate;
    unite op.qualifier.polymorph from pi;
  end block;
  ADDINSTR(op);
  
  -- Now codegen the body of the inspect
  inspect prog in ABSPROG.programs[args.cgData.Proc.id] begin
    inspect scope in prog.executable_part.scopes
	  [args.stmt.qualifier.inspect_polymorph.scope] begin
      call FNS.cgClause(scope.clause,args.cgData);
    end inspect;
  end inspect;

  -- Finally put together the 'endinspect_poly' statement to close
  -- things off
  new op;
  op.opcode <- interpform!opcode#'endinspect_poly';
  new op.operands;
  insert dstAddr into op.operands;
  unite op.qualifier.empty from empty;
  ADDINSTR(op);
  
  return args;
  
end process
