/*
 *                         OpenSplice DDS
 *
 *   This software and documentation are Copyright 2006 to TO_YEAR PrismTech
 *   Limited, its affiliated companies and licensors. All rights reserved.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

#include "idl.h"
#include "idl_extern.h"

/*
 * Constructor(s) and destructor
 */
AST_Value::AST_Value ()
: 
   pd_abstract (false),
   pd_value_inherits (NULL),
   pd_n_value_inherits (0),
   pd_truncatable (false),
   pd_custom (false)
{}

AST_Value::AST_Value
(
   bool abstract,
   bool custom,
   bool truncatable,
   UTL_ScopedName *n,
   AST_Value **ih,
   long nih,
   AST_Interface **supports,
   long nsupports,
   const UTL_Pragmas &p
)
   : AST_Decl (AST_Decl::NT_value, n, p),
     AST_Type (AST_Decl::NT_value, n, p),
     UTL_Scope (AST_Decl::NT_value, n, p),
     AST_Interface (true, false, n, supports, nsupports, p),
     pd_abstract (abstract),
     pd_value_inherits (ih),
     pd_n_value_inherits (nih),
     pd_truncatable (truncatable),
     pd_custom (custom)
{
}

/*
 * Private operations
 */

/*
 * Public operations
 */


/*
 * Redefinition of inherited virtual operations
 */

AST_StateMember *AST_Value::fe_add_state_member(AST_StateMember *t)
{
   AST_Decl *d;

   /*
    * Can't add to interface which was not yet defined
    */

   if (!is_defined())
   {
      idl_global->err()->error2(UTL_Error::EIDL_DECL_NOT_DEFINED, this, t);
      return NULL;
   }

   /*
    * Already defined and cannot be redefined? Or already used?
    */
   if ((d = lookup_for_add (t)) != NULL)
   {
      if (!can_be_redefined(d))
      {
         idl_global->err()->error3(UTL_Error::EIDL_REDEF, t, this, d);
         return NULL;
      }

      if (referenced(d))
      {
         idl_global->err()->error3(UTL_Error::EIDL_DEF_USE, t, this, d);
         return NULL;
      }

      if (t->has_ancestor(d))
      {
         idl_global->err()->redefinition_in_scope(t, d);
         return NULL;
      }
   }

   /*
    * Add it to scope
    */
   add_to_scope(t);

   /*
    * Add it to set of locally referenced symbols
    */
   add_to_referenced(t, false);

   return t;
}

AST_Initializer *AST_Value::fe_add_initializer(AST_Initializer *t)
{
   AST_Decl *d;

   /*
    * Can't add to interface which was not yet defined
    */

   if (!is_defined())
   {
      idl_global->err()->error2(UTL_Error::EIDL_DECL_NOT_DEFINED, this, t);
      return NULL;
   }

   /*
    * Already defined and cannot be redefined? Or already used?
    */
   if ((d = lookup_for_add (t)) != NULL)
   {
      if (!can_be_redefined(d))
      {
         idl_global->err()->error3(UTL_Error::EIDL_REDEF, t, this, d);
         return NULL;
      }

      if (referenced(d))
      {
         idl_global->err()->error3(UTL_Error::EIDL_DEF_USE, t, this, d);
         return NULL;
      }
   }

   /*
    * Add it to scope
    */
   add_to_scope(t);

   /*
    * Add it to set of locally referenced symbols
    */
   add_to_referenced(t, false);

   return t;
}

/*
 * Dump this AST_Value node to the ostream o
 */
void
AST_Value::dump(ostream &o)
{
   long i;

   o << (local() == true ? "local" : "") << " valuetype ";
   local_name()->dump(o);
   o << " ";

   if (pd_n_value_inherits > 0)
   {
      o << ": ";

      for (i = 0; i < pd_n_value_inherits; i++)
      {
         pd_value_inherits[i]->local_name()->dump(o);

         if (i < pd_n_value_inherits - 1)
         {
            o << ", ";
         }
      }
   }

   o << " {\n";
   AST_Interface::dump(o);
   idl_global->indent()->skip_to(o);
   o << "}";
}

/*
 * Data accessors
 */

bool AST_Value::is_abstract ()
{
   return pd_abstract;
}

bool AST_Value::is_custom ()
{
   return pd_custom;
}

bool AST_Value::is_truncatable ()
{
   return pd_truncatable;
}

void AST_Value::set_custom (bool v)
{
   pd_custom = v;
}

void AST_Value::set_truncatable (bool v)
{
   pd_truncatable = v;
}

AST_Value **
AST_Value::value_inherits()
{
   return pd_value_inherits;
}

void
AST_Value::set_value_inherits(AST_Value **i)
{
   pd_value_inherits = i;
}

long
AST_Value::n_value_inherits()
{
   return pd_n_value_inherits;
}

void
AST_Value::set_n_value_inherits(long i)
{
   pd_n_value_inherits = i;
}

/*
 * Narrowing methods
 */
IMPL_NARROW_METHODS3(AST_Value, AST_Interface, AST_Type, UTL_Scope)
IMPL_NARROW_FROM_DECL(AST_Value)
IMPL_NARROW_FROM_SCOPE(AST_Value)
