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

-- This process transforms an expression represented as an
-- exprTree!expr into a list of Hermes statements that will compute
-- the expression.

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

exprAssemble: using (exprTree)

process (Q: exprAssembleQ)
  
declare
  args: exprAssemble;
begin
block begin
  receive args from Q;
  
  select exprType#(case of args.expr)
  where (exprType#'object')
    -- this is a leaf... give them back an empty statement list
    new args.stmts;
    
  where (exprType#'tree')
    -- tree node... assemble its args, then produce a statement for
    -- this tree
    reveal args.expr.tree;
    block declare
      argstmts: predefined!statements;
      exprAssemble: exprAssembleFn;
      stmt: predefined!statement;
    begin
      new args.stmts;
      exprAssemble <- exprAssembleFn#(procedure of program#currentprogram);
      -- Assemble this statement's args
      for arg in args.expr.tree.args[] inspect
	argstmts <- predefined!statements#(exprAssemble(arg));
	merge argstmts into args.stmts;
      end for;
      -- Now build the statement for this tree node
      new stmt;
      stmt.id <- predefined!statementid#unique;-- arbitrary id
      stmt.operator := args.expr.tree.opcode;
      new stmt.operands;
      -- destination operand comes first for most statements
      if B(B(stmt.operator <> predefined!operator#'call') and
	      B(stmt.operator <> predefined!operator#'expression_block'))
      then
	insert objectname#(copy of args.expr.tree.dst) into stmt.operands;
      end if;
      for arg in args.expr.tree.args[] inspect
	select exprType#(case of arg)
	where (exprType#'object')
	  reveal arg.obj;
	  insert objectname#(copy of arg.obj) into stmt.operands;
	where (exprType#'tree')
	  reveal arg.tree;
	  insert objectname#(copy of arg.tree.dst) into stmt.operands;
	otherwise
	  exit cantHappen;
	end select;
      end for;
      -- destination operand comes last for 'call' statement
      if B(stmt.operator = predefined!operator#'call') then
	insert objectname#(copy of args.expr.tree.dst) into stmt.operands;
      end if;
      stmt.qualifier := args.expr.tree.qual;
      stmt.prag := args.expr.tree.prag;
      insert stmt into args.stmts;
    end block;
    
  otherwise
    exit cantHappen;
  end select;
  
  return args;
  
on exit(cantHappen)
  print S("Exit to cantHappen in exprAssemble");
end block;
end process
