/// TKS_ClassDeclMethod.cpp
///
/// (c) 2001-2009 Bastian Spiegel <bs@tkscript.de>
///     - distributed under the terms of the GNU general public license (GPL).
///

#include "tks.h"
#include "tks_inc_compiler.h"
#include "tks_inc_class.h"


TKS_ClassDeclMethod::TKS_ClassDeclMethod(void) {
   vtable           = NULL;
   protection_flags = TKS_PROT_NONE;
   b_this_mutex     = 0;
   b_abstract       = 0;
   b_virtual        = 0;
}

TKS_ClassDeclMethod::~TKS_ClassDeclMethod() {
   if(NULL != vtable)
   {
      // Note: node allocator batch-frees all vtables during cleanup
#ifndef TKS_USE_NODEALLOCATOR
      delete [] vtable;
#endif // TKS_USE_NODEALLOCATOR
      vtable = NULL;
   }
}

void TKS_ClassDeclMethod::allocVTable(void) {
   sUI i;
#ifdef TKS_USE_NODEALLOCATOR
   vtable = (TKS_ClassDeclMethod**) Dtkscompiler->static_node_allocator->alloc(sizeof(TKS_ClassDeclMethod*) * Dtkscompiler->class_decls.num_elements);
#else
   vtable = new TKS_ClassDeclMethod*[TKS_MAX_CLASSDECLS];
#endif // TKS_USE_NODEALLOCATOR
   for(i=0; i<Dtkscompiler->class_decls.num_elements; i++)  
   { 
      vtable[i] = NULL;
   }
   vtable[function.parent_class->class_id] = this; // Add reference to self
}

#ifdef TKS_CHECK_ABSTRACTCALL
sBool TKS_ClassDeclMethod::isAbstractInClass(TKS_ClassDecl *_cd) {
   //
   // Check whether this method was declared in _cd or one of its baseclasses
   //
   if(_cd != function.parent_class)
   {
      if(vtable)
      {
         if(vtable[_cd->class_id])
         {
            // OK: was implemented in given class
            return vtable[_cd->class_id]->b_abstract;
         }
      }
   }
   return 1;
}
#endif // TKS_CHECK_ABSTRACTCALL

