/* (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: o_var.c */
/* Author: David F. Bacon */
#ifndef lint
static char sccsinfo[] = "@(#)o_var.c	1.8 3/13/90";
#endif

#include "ops.h"
#include "storage.h"

#define Dst (DstObj->value)
#define Src (SrcObj->value)

extern datarep dr_bottom, dr_variant, dr_enumeration;

NILOP(o_unite)
{
    void re_finalize();
    dfd_variant *newvar;

    if (DstObj->tsdr->number is dr_bottom.number)
      if ((newvar = getdotmain(VARIANT_SIZE)) is nil) {
	  raise(Depletion);
	  return;
      }
      else 
	Dst.variant = newvar;
    else
      re_finalize(& Dst.variant->data[VARIANT_COMPONENT], F_DISCARD,
		  args->sched);
				/* if not already bottom, finalize the */
				/*  component. */
	
    Dst.variant->info.variant_case = args->qualifiers.integer;
				/* set the case as passed in the qualifier. */

    Dst.variant->data[VARIANT_COMPONENT] = *(SrcObj);
				/* copy entire object cell from src to dst */

    set_init(DstObj, dr_variant);
    set_bottom(SrcObj);		/* [1] make source object uninit */
}


NILOP(o_dissolve)
{
    void re_finalize();
    extern flag cherm_flag;

    OPCHK(SrcObj,variant);
    if (not cherm_flag)
      re_finalize(DstObj, F_DISCARD, args->sched);
				/* finalize the value of the destination; */
    *(DstObj) = Src.variant->data[VARIANT_COMPONENT];
    { freedotmain(Src.variant, VARIANT_SIZE); }
    set_bottom(SrcObj);
}


NILOP(o_reveal)
{
    OPCHK(DstObj,variant);
    if (args->qualifiers.integer isnt Dst.variant->info.variant_case)
      raise(CaseError);
}


/*ARGSUSED*/
NILOP(o_hide)
{
/* i'm a no-op and i'm okay.  actually, i'm a typestate assertion. */
    OPCHK(DstObj,variant);
}


NILOP(o_case)
{
    OPCHK(SrcObj,variant);
    Dst.enumeration = Src.variant->info.variant_case;
    set_init(DstObj, dr_enumeration);
}


void
fin_variant(value, f_op, sched)
valcell value;
finalize_op f_op;
schedblock *sched;
{
    void re_finalize();

    re_finalize(& value.variant->data[VARIANT_COMPONENT], f_op, sched);
    { freedotmain(value.variant, VARIANT_SIZE); }
}


predef_exception
cp_variant(dst, src)
valcell *dst, src;
{
    predef_exception re_copy();
    predef_exception retcode;
    valcell newvar;


    if ((newvar.variant = (dfd_variant *) getdotmain(VARIANT_SIZE)) is nil)
      return(Depletion);
    newvar.variant->info.variant_case = src.variant->info.variant_case;
    retcode = re_copy(& src.variant->data[VARIANT_COMPONENT],
		      & newvar.variant->data[VARIANT_COMPONENT]);
    if (retcode is Normal)
      dst->variant = newvar.variant;
    else
      { freedotmain(newvar.variant, VARIANT_SIZE); }
    return(retcode);
}


status
eq_variant(v1, v2)
valcell v1, v2;
{
    status re_equal();

    if (v1.variant->info.variant_case is v2.variant->info.variant_case)
      return(re_equal(& v1.variant->data[VARIANT_COMPONENT],
		    & v2.variant->data[VARIANT_COMPONENT]));
    else
      return(FAILURE);
}
