2005/5/9

     
 

ScriptObject.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 


#include "ScriptObject.h"
#include "Script.h"
#include "ScriptSource.h"
#include "ScriptException.h"
#include "ScriptEval.h"
#include "ScriptExpr.h"

#include <acdk/lang/dmi/ClazzAttributesRes.h>
#include <acdk/lang/dmi/DmiNamedArg.h>
#include <acdk/lang/dmi/DmiDelegate.h>
#include <acdk/lang/sys/LocalGcHeap.h>

#include <acdk/lang/sys/core_value_scope.h>
#include <acdk/lang/sys/core_system.h>

#undef DOUT
//#define LOCAL_DEBUG
#if defined(LOCAL_DEBUG)

RString spaces(int count);
#define DOUT(exp) acdk::lang::sys::coreout << exp << acdk::lang::sys::eofl
#else
/FONT>
#define DOUT(strexpr) do { } while(false)
#endif
/FONT>


namespace acdk {
namespace cfgscript {


using namespace acdk::io;
using namespace acdk::lang::reflect;
using namespace acdk::lang::dmi;


typedef acdk::lang::sys::core_value_scope<const acdk::lang::dmi::ClazzInfo*> StackedClazzInfo;
typedef acdk::lang::sys::core_value_scope<const acdk::lang::dmi::ClazzMethodInfo*> StackedClazzMethodInfo;

void executeFieldInitializer(const acdk::lang::dmi::ClazzInfo* ci, const acdk::lang::dmi::ClazzFieldInfo* fi, INOUTP(RProps) target, PEStack& stack)
{
  target->set(fi->name, new DmiObject(fi->type), PropsNoParentWrite);
  Field field(ci, fi);
  if (field.hasMetaAttribute("_cfgscript_source") == false)
    return;

  RScriptMethodInfo methodsource =  (RScriptMethodInfo)field.getMetaAttribute("_cfgscript_source")->value;
  //RScript script = Script::getCurrentScript();
  RScript script = (RScript)Class::getSingeltonClass(ci)->getMetaAttribute("_cfgscript_script")->value;
  
  int execIdx = ExecutionStack::get()->push(new ExecutionStackFrame(script, methodsource->begintokenIndex, ci, 0));

  //StackedClazzInfo _savedci(script->_currentClazz, ci);
  //stack.props->dump();
  //System::out->println("====");
  target->addParentProps(stack.props);
  PropsScope propsscope(stack.props, target, PropsNoParentWrite | PropsParentRead);
  
  acdk::lang::sys::core_value_scope<int> tokenIdxscope(stack.tokenizer._tokenIdx, methodsource->begintokenIndex);
  acdk::lang::sys::core_value_scope<int> tokenEndIdscope(stack.tokenizer._endTokenIdx, methodsource->endtokenIndex);

  
  //stack.props->dump();
  bool erg = ExpressionParseNode().parseExecute(stack);
  if (erg == false)
    return;
  target->assign(fi->name, new DmiObject(stack.pop().val));
  ExecutionStack::get()->pop(execIdx);
}

void executeFieldInitializer(const acdk::lang::dmi::ClazzInfo* ci, const acdk::lang::dmi::ClazzFieldInfo* fi, INOUTP(RProps) target)
{
  target->set(fi->name, new DmiObject(fi->type), PropsNoParentWrite);
  Field field(ci, fi);
  if (field.hasMetaAttribute("_cfgscript_source") == false)
    return;

  RScriptMethodInfo methodsource =  (RScriptMethodInfo)field.getMetaAttribute("_cfgscript_source")->value;
  //RScript script = Script::getCurrentScript();
  RScript script = (RScript)Class::getSingeltonClass(ci)->getMetaAttribute("_cfgscript_script")->value;
  //StackedClazzInfo _savedci(script->_currentClazz, ci);
  PropsScope propsscope(script->currentProps, target, PropsNoParentWrite | PropsParentRead);
  
  PEStack stack(script, target, methodsource->begintokenIndex, methodsource->endtokenIndex);
  
  //StackedClazzMethodInfo _savemi(script->_currentClazzMethod, methinf);
  
  int execIdx = ExecutionStack::get()->push(new ExecutionStackFrame(script, methodsource->begintokenIndex, ci, 0));
  bool erg = ExpressionParseNode().parseExecute(stack);
  if (erg == false)
    return;
  target->assign(fi->name, new DmiObject(stack.pop().val));
  ExecutionStack::get()->pop(execIdx);
  
}

using namespace acdk::lang::dmi;
void
createStaticMember(const ClazzInfo* ci, ClazzFieldInfo* fi, PEStack& stack)
{
  RClass cls = Class::getSingeltonClass(ci);
  if (cls->hasMetaAttribute("_cfgscript_static_members") == false)
  {
    cls->setMetaAttribute("_cfgscript_static_members", (acdk::lang::Object)new Props("static_members"));
  }
  
  RProps statics =  (RProps)cls->getMetaAttribute("_cfgscript_static_members")->value;
  executeFieldInitializer(ci, fi, statics, stack);

}


ScriptObject::ScriptObject(const acdk::lang::dmi::ClazzInfo* ci)
: _castRecGuard(false)
, _locals(new Props("dynamic_members"))
, _dmiProxies(new ObjectArray(0))
, _superObject(Nil)
, _finalizeCalled(false)
, _scriptClazzInfo(ci)
, _derivedObject(Nil)
//, _proxyCount(0)
{
  ACDK_SAFE_CONSTRUCTOR();
  //setLocalGc(true);
  //RScript script = (RScript)Class::getSingeltonClass(ci)->getMetaAttribute("_cfgscript_script")->value;
  DOUT((void*)this << "; ScriptObject::ScriptObject: " << ci->name);
  /*
  RScript script = ExecutionStack::getTop()->_script;

  if (script != Nil && script->currentProps != Nil)
  {
    _locals->addParentProps(script->currentProps);
  }*/

  RClass cls = Class::getSingeltonClass(ci);
  if (cls->hasMetaAttribute("_cfgscript_static_members") == true)
  {
    RProps statics =  (RProps)cls->getMetaAttribute("_cfgscript_static_members")->value;
    _locals->addParentProps(statics);
  }
  if (cls->hasMetaAttribute("_cfgscript_module_props") == true)
  {
    RProps module =  (RProps)cls->getMetaAttribute("_cfgscript_module_props")->value;
    _locals->addParentProps(module);
  }
  int i;
  //PEStack stack(script, props, methodsource->begintokenIndex, methodsource->endtokenIndex);
  for (i = 0; i < ci->getFieldsCount(); ++i)
  {
    executeFieldInitializer(ci, ci->fields[i], _locals);
  }
  
  for (i = 0; i < ci->getInterfacesCount(); ++i)
  {
    if (_isDmiProxyInterface(ci->interfaces[i]->type) == true)
    {
      RClass cls = Class::getSingeltonClass(ci->interfaces[i]->type);
      cls->getDmiProxies(_dmiProxies, this, 0);
    }
  }
  for (i = 0; i < _dmiProxies.length(); ++i)
  {
    DmiProxyBase* pb;
    if ((pb = dynamic_cast<DmiProxyBase*>(_dmiProxies[i].impl())) != 0)
    {
      acdk::lang::Object* ro = (acdk::lang::Object*)_dmiProxies[i]._ref_this();
      //_sharedRefs.registerSharedObjectRefs(((DmiProxyBase*)_dmiProxies[i].impl())->_dmiTarget._ref_this(), (acdk::lang::Object*)_dmiProxies[i]._ref_this());
    }
  } 
  _setObjectRefFlag(true, ObjectBase::ObjectHasLocalGc);
}

void 
ScriptObject::setImplementation(IN(RScriptObject) impl)
{
  _derivedObject = impl;
}

void 
ScriptObject::setSuperObject(IN(acdk::lang::Object) obj)
{
  _superObject = obj;

  DOUT((void*)this << ";setSuperObect(" <<  (void*)_superObject.impl() << ")");
  DmiProxyBase* dmiproxy;
  if (_superObject != Nil && (dmiproxy = dynamic_cast<DmiProxyBase*>(_superObject.impl())) != 0)
  {
    dmiproxy->setDmiTarget(this);
    //_sharedRefs.registerSharedObjectRefs(dmiproxy->_dmiTarget._ref_this(), _superObject._ref_this());
  }
  else if (instanceof(_superObject, ScriptObject) == true)
  {
    RScriptObject superSo(_superObject);
    superSo->setImplementation(this);
    //_sharedRefs.registerSharedObjectRefs((acdk::lang::Object*)superSo->_derivedObject._ref_this(), _superObject._ref_this());
  }
}

ScriptObject::~ScriptObject()
{
  DOUT((void*)this << " ScriptObject::~ScriptObject(): " << _scriptClazzInfo->name);
  //_sharedRefs.unregisterAll();
  if (instanceof(_superObject, ScriptObject) == true)
    RScriptObject(_superObject)->_derivedObject = Nil;
  _superObject = Nil;
}


void 
ScriptObject::_setFinalized()
{
  _finalizeCalled = true;
  if (instanceof(_superObject, ScriptObject) == true)
    RScriptObject(_superObject)->_setFinalized();
  for (int i = 0; i < _dmiProxies.length(); ++i)
  {
    if (instanceof(_dmiProxies[i], ScriptObject) == true)
    {
      RScriptObject so(_dmiProxies[i]);
      so->_setFinalized();
    }
  }
}

void 
ScriptObject::finalize()
{
  getMostDerived()->_invokeFinalize();
}

void ScriptObject::_invokeFinalize()
{
  if (_finalizeCalled == true)
    return;
  _setFinalized();;
  {
  acdk::lang::dmi::ScriptVar ret;
  acdk::lang::dmi::ScriptVarArray args;
  ::acdk::lang::dmi::AcdkStdWeakTypeDmiClient dmiclient(_locals->getCastFlags());

  const acdk::lang::dmi::ClazzMethodInfo* methinf = lookupMethod(_scriptClazzInfo, "finalize", args, Nil, dmiclient, MiIvDeclared | MiIvNoThrowIfNotFound);
  if (methinf == 0)
    return;
  //_setObjectRefFlag(true, NoRefCounting);
  lockMem(true);
  standardDispatchFromTopMost("finalize", ret, args, dmiclient, Nil,
                                MiIvDeclared,
                                _scriptClazzInfo,
                                methinf);
  }
}


void releaseDmiProxy(INOUT(acdk::lang::Object) obj)
{
  if (obj == Nil)
    return;
  DmiProxyBase* proxy = dynamic_cast<DmiProxyBase*>(obj.impl()) ;
  if (proxy != 0)
    proxy->setDmiTarget(Nil);
  obj = Nil;
}

bool canReleased(IN(acdk::lang::Object) obj)
{
  if (obj == Nil)
    return true;
  DmiProxyBase* proxy = dynamic_cast<DmiProxyBase*>(obj.impl()) ;
  if (proxy == 0)
    return true;
  if (proxy->_dmiProxyGetTarget()->refCount() <= 2)
    return true;
  return false;
}

void 
ScriptObject::getCollectableFields(FieldReferences& fields)
{
  fields.push_back((acdk::lang::Object*)_derivedObject._ref_this());
  fields.push_back((acdk::lang::Object*)_superObject._ref_this());
  fields.push_back((acdk::lang::Object*)_dmiProxies._ref_this());
}

bool 
ScriptObject::_gc_releaseRef(bool force) const
{
  if (_releaseRefCount() == true) 
    return true;
  if (isWeakRef() == true  ||
      isMemLocked() == true  ||
      isStackRef() == true ||
      (const_cast<acdk::lang::Object*>(static_cast<const acdk::lang::Object*>(this))->allocator()->flags & acdk::lang::sys::NoRefCountAllocatorType) != 0) 
    return false;

  int refC = refCount();
  int potRefC = 0;
  if (_derivedObject != Nil)
    ++potRefC;
  if (_superObject != Nil)
    ++potRefC;
  potRefC += _dmiProxies->length();
  if (refC <= potRefC)
    return sys::LocalGcHeap::gcObject((acdk::lang::Object*)this);
  return false;
}

//virtual 
::acdk::lang::dmi::ClazzInfo* 
ScriptObject::getClazzInfo()  
{ 
  if (_derivedObject != Nil)
    return _derivedObject->getClazzInfo();
  return const_cast<acdk::lang::dmi::ClazzInfo*>(_scriptClazzInfo); 
}
 
bool 
ScriptObject::isDirectSuper(const ::acdk::lang::dmi::ClazzInfo* ci)
{
  if (_scriptClazzInfo == ci)
    return true;
  if (_superObject != Nil && instanceof(_superObject, ScriptObject) == true)
  {
    RScriptObject sobj(_superObject);
    return sobj->isDirectSuper(ci);
  }
  return false;
}

RScriptObject 
ScriptObject::getMostDerived()
{
  RScriptObject o = this;
  while (o->_derivedObject != Nil)
    o = o->_derivedObject;
  return o;
}

//static 
bool 
ScriptObject::_isScriptInterface(const acdk::lang::dmi::ClazzInfo* ci)
{
  RMetaAttribute ma = Class::getSingeltonClass(ci)->getMetaAttribute("_cfgscript_script");
  if (ma != Nil)
    return true;
  return false;
}

acdk::lang::Object* 
ScriptObject::_cast(const ::acdk::lang::dmi::ClazzInfo* ci)
{
  DOUT((void*)this << "; ScriptObject::_cast from " << _scriptClazzInfo->name << " to " << ci->name);
  if (ci == _scriptClazzInfo)
    return this;
  return getMostDerived()->_castFromTopMost(ci);
}

acdk::lang::Object* 
ScriptObject::_castFromObject(IN(acdk::lang::Object) o, const ::acdk::lang::dmi::ClazzInfo* ci)
{
  if (o == Nil)
    return 0;
  if (dynamic_cast<DmiProxyBase*>(o.impl()) != 0)
  {
    if (ci->assignableFrom(o->getClazzInfo()) == true)
      return o;
  }
  else if (instanceof(o, ScriptObject) == true)
  {
    RScriptObject so(o);
    acdk::lang::Object* o = so->_castFromTopMost(ci);
    if (o != 0)
      return o;
  }
  else if (ci->assignableFrom(_scriptClazzInfo) == true && _isScriptInterface(ci) == false)
  {
    // no dmi object available
    return o;
  }
  if (ci->assignableFrom(_scriptClazzInfo) == true)
  {
    if (_isScriptInterface(ci) == true)
      return this;
  }
  return 0;
}

acdk::lang::Object* 
ScriptObject::_castFromTopMost(const ::acdk::lang::dmi::ClazzInfo* ci)
{
  if (ci == _scriptClazzInfo)
    return this;
  if (ci == Object::clazzInfo())
    return this;
  acdk::lang::Object* ret = _castFromObject(_superObject, ci);
  if (ret != 0)
    return ret;

  for (int i = 0; i < _dmiProxies->length(); ++i)
  {
    ret = _castFromObject(_dmiProxies[i], ci);
    if (ret != 0)
      return ret;
  }
  return 0;
}



using namespace acdk::lang::dmi;


void ajustFlags(IN(RExecutionStackFrame) esf, const ClazzInfo* ci, int& flags)
{
  if (esf == Nil)
    return;
  if (esf->_currentClazzInfo != 0)
  {
    if (esf->_currentClazzInfo == ci)
    {
      flags &= ~MiPublic & ~MiProtected; flags |= MiPrivate;
    }
    else if (esf->_currentClazzInfo->assignableFrom(ci) == true)
    {
      flags &= ~MiPublic; flags |= MiProtected;
    }
  }
}

const acdk::lang::dmi::ClazzMethodInfo* 
ScriptObject::standardDispatch(  IN(acdk::lang::RString) fname, acdk::lang::dmi::ScriptVar& ret, 
                                acdk::lang::dmi::ScriptVarArray& args, 
                                acdk::lang::dmi::DmiClient& dc,
                                IN(::acdk::lang::RStringArray) namedArgs/* = Nil*/,
                                int flags,
                                const acdk::lang::dmi::ClazzInfo* clazzinfo,
                                const acdk::lang::dmi::ClazzMethodInfo* methinf/* = 0*/)
{
  
  //static bool recursionsGuard = false;
  DOUT((void*)this << "; ScriptObject::standardDispatch: " << _scriptClazzInfo->name);
  if (flags & MiIvNoWeakBind) // called via super.call()
    return standardDispatchFromTopMost(fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
  return getMostDerived()->standardDispatchFromTopMost(fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
}
  
acdk::lang::Object 
ScriptObject::_findSuperByClazz(const acdk::lang::dmi::ClazzInfo* clazzinfo)
{
  if (clazzinfo == _scriptClazzInfo)
    return this;
  if (_superObject == Nil)
    ; // ooop;
  if (instanceof(_superObject, ScriptObject) == true)
    return RScriptObject(_superObject)->_findSuperByClazz(clazzinfo);
  return _superObject;
}

const acdk::lang::dmi::ClazzMethodInfo* 
ScriptObject::standardDispatchFromTopMost(  IN(acdk::lang::RString) fname, acdk::lang::dmi::ScriptVar& ret, 
                                acdk::lang::dmi::ScriptVarArray& args, 
                                acdk::lang::dmi::DmiClient& dc,
                                IN(::acdk::lang::RStringArray) namedArgs/* = Nil*/,
                                int flags,
                                const acdk::lang::dmi::ClazzInfo* clazzinfo,
                                const acdk::lang::dmi::ClazzMethodInfo* methinf/* = 0*/)
{

  const ClazzInfo* ci = clazzinfo;

  if (methinf == 0 || methinf->flags & MiMiVirtual) // virtual methods may be overwriten
  {
    //RScript script = Script::getCurrentScript();
    RMetaAttribute ma = Class::getSingeltonClass(_scriptClazzInfo)->getMetaAttribute("_cfgscript_script");
    RScript script;
    if (ma != Nil)
      script = (RScript)ma->value;
    RExecutionStackFrame esf = ExecutionStack::getTop();

    ci = _scriptClazzInfo;

    ajustFlags(esf, ci, flags);
    ASCLITERAL(poke);
    ASCLITERAL(peek);

    if (fname->equals(lit_poke) == true || fname->equals(lit_peek) == true)
    {
      RString name = args[0].getStringVar();
      const ClazzInfo* sicci = ci;
      const ClazzFieldInfo* fi = ci->findField(sicci, name, (flags | MiPrivate) & ~MiPublic & ~MiProtected);
      
      if ((void*)fi->_scopeParent != (void*)ci && _superObject != Nil)
      {
        acdk::lang::Object superObject = _findSuperByClazz((const acdk::lang::dmi::ClazzInfo*)fi->_scopeParent);

        ajustFlags(esf, (const ClazzInfo*)fi->_scopeParent, flags); // ajust flags with new ci
        fi = ci->findField(sicci, name, flags); // find again
        int memberAccessFlag = 0;
        if (instanceof(_superObject, ScriptObject) == true)
        {
          RScriptObject(superObject)->standardDispatchFromTopMost(fname, ret, args, dc, namedArgs, memberAccessFlag, (const ClazzInfo*)fi->_scopeParent, 0);
        } 
        else 
        {
          memberAccessFlag |= MiIvNoWeakBind;
          if (fname->equals(lit_poke) == true)
          {
            superObject->setMember(name, args[1], dc, flags  | memberAccessFlag);
            ret = args[1];
          }
          else
          {
            ret = superObject->getMember(name, dc, flags | memberAccessFlag);
          }
        }
        return (methinf == 0 ? (const ClazzMethodInfo*)1 : methinf);
      }
      if (_locals->hasValue(name) == false)
        THROW1(DmiException, RString("Class ") + ci->name + " has no field named " + name);
      if (fname->equals(lit_poke) == true)
      {
        _locals->assign(name, new DmiObject(args[1]));
        ret = args[1];
      } 
      else // peek
      {
        ret= *_locals->get(name);
      }
      return methinf;
    }
    
    methinf = lookupMethod(ci, fname, args, namedArgs, dc, flags);
    //methinf = lookupMethodNoPolymorph(ci, fname, args, namedArgs, dc, flags);
    if (methinf == 0)
      ClazzMethodInfo::throwMethodNotFound(clazzinfo, fname, flags, dc._formatFlags);
  }
  if (methinf->dispatch != 0)
  {
    if (ScriptObject::dispatch != methinf->dispatch)
    {
      // call native implemented, but with dmiproxy if virtual
      
      return methinf->dispatch(this, fname, ret, args, dc, namedArgs, flags | ::acdk::lang::dmi::MiIvNoWeakBind, ci, methinf);
      

      
    }
    else
      return methinf->dispatch(this, fname, ret, args, dc, namedArgs, flags, ci, methinf);
  }
  return 0;
}


//static 
const ::acdk::lang::dmi::ClazzMethodInfo* 
ScriptObject::static_dispatch(IN(acdk::lang::RString) fname, ::acdk::lang::dmi::ScriptVar& ret, 
                                               ::acdk::lang::dmi::ScriptVarArray& args, 
                                               ::acdk::lang::dmi::DmiClient& dc,
                                               IN(::acdk::lang::RStringArray) namedArgs,
                                                int flags,
                                                const ::acdk::lang::dmi::ClazzInfo* clazzinfo,
                                                const ::acdk::lang::dmi::ClazzMethodInfo* methinf)
{
  const ClazzInfo* ci = clazzinfo;
  RClass cls = Class::getSingeltonClass(ci);
  
  if (methinf == 0)
  {
    RExecutionStackFrame esf = ExecutionStack::getTop();
    RScript script = (RScript)cls->getMetaAttribute("_cfgscript_script")->value;
    ajustFlags(esf, ci, flags);
    ASCLITERAL(peek_static);
    ASCLITERAL(poke_static);
    ASCLITERAL(GetClass);
    if (fname->equals(lit_peek_static) == true || fname->equals(lit_poke_static) == true)
    {
      if (cls->hasMetaAttribute("_cfgscript_static_members") == false)
        THROW1(DmiException, "in peek_static or poke_static: Class has no static members: " + cls->getName());
      if (fname->equals(lit_peek_static) == true)
      {
        RString fieldName = args[0].getStringVar();
        RProps statics =  (RProps)cls->getMetaAttribute("_cfgscript_static_members")->value;
        ret = *statics->get(fieldName);
        return (::acdk::lang::dmi::ClazzMethodInfo* )1; 
      }
      else if (fname->equals(lit_poke_static) == true)
      {
        RString fieldName = args[0].getStringVar();
        RClass cls = Class::getSingeltonClass(ci);
        RProps statics =  (RProps)cls->getMetaAttribute("_cfgscript_static_members")->value;
        statics->set(fieldName, new DmiObject(args[1]));
        ret = args[1];
        return (::acdk::lang::dmi::ClazzMethodInfo* )1; 
      }
    }
    else if (fname->equals(lit_GetClass) == true && args.size() == 0)
    {
      ret = &Class::getSingeltonClass(clazzinfo);
      return (::acdk::lang::dmi::ClazzMethodInfo* )1;
    }
    methinf = lookupMethod(ci, fname, args, namedArgs, dc, flags);
    
    if (methinf == 0)
      ClazzMethodInfo::throwMethodNotFound(clazzinfo, fname, flags, dc._formatFlags);
  }
  if (methinf->dispatch != 0)
    return methinf->dispatch(0, fname, ret, args, dc, namedArgs, flags, ci, methinf);
  return (::acdk::lang::dmi::ClazzMethodInfo* )0;
}




//virtual 
bool 
ScriptObject::isDmiOverLoaded(const acdk::lang::dmi::ClazzInfo* ci, IN(RString) funcname, const acdk::lang::dmi::ClazzMethodInfo* mi, acdk::lang::dmi::ClazzMethodArgInfo** const args)
{
  if (mi != 0)
  {
    if (reinterpret_cast<const acdk::lang::dmi::ClazzInfo*>(mi->_scopeParent) == getClazzInfo())
      return true;
  }
  const ClazzInfo* nci = _scriptClazzInfo;
  ::acdk::lang::dmi::AcdkStdWeakTypeDmiClient dmiclient;
  const ClazzMethodInfo* nmi = StdDispatch::lookupMethod(nci, funcname, args, dmiclient, 0);
  if (nmi->flags & MiMiDmiImpl)
    return true;
  //const acdk::lang::dmi::ClazzMethodInfo* methinf = lookupMethodNoPolymorph(ci, funcname, flags);
  return false;
}



//static 
const ::acdk::lang::dmi::ClazzMethodInfo* 
ScriptObject::dispatch(
                                                        ::acdk::lang::Object* This, 
                                                         IN(acdk::lang::RString) fname, 
                                                         ::acdk::lang::dmi::ScriptVar& ret, 
                                                         ::acdk::lang::dmi::ScriptVarArray& args, 
                                                         ::acdk::lang::dmi::DmiClient& dc,
                                                         IN(::acdk::lang::RStringArray) namedArgs,
                                                         int flags,
                                                         const ::acdk::lang::dmi::ClazzInfo* clazzinfo,
                                                         const ::acdk::lang::dmi::ClazzMethodInfo* methinf)
{
  RScriptObject thisobj;
  const ClazzInfo* ci = clazzinfo;
  if (flags & MiIvConstructor)
  {
    RScriptObject s = new ScriptObject(clazzinfo);
    ret = inOf(s);
    thisobj = s;
    This = &thisobj;
  }
  else if (This != 0)
  {
    thisobj = RScriptObject(This);
  }
  

  //RScript script = Script::getCurrentScript();
  RClass cls = Class::getSingeltonClass(ci);
  RScript script = (RScript)cls->getMetaAttribute("_cfgscript_script")->value;
  RProps moduleProps = (RProps)cls->getMetaAttribute("_cfgscript_module_props")->value;
  
  
  Method met(ci, methinf);
  RScriptMethodInfo methodsource =  (RScriptMethodInfo)met.getObjectMetaAttribute("_cfgscript_source");
  
  int esfIdx = ExecutionStack::get()->push(new ExecutionStackFrame(script, methodsource->begintokenIndex, methinf));
  
  RExecutionStackFrame esf = ExecutionStack::getTop();
  
  RProps locals;
  if (thisobj != Nil)
    locals = thisobj->_locals;
  else
    locals = script->currentProps;

  
  RProps props = new Props("method_locals", PropsParentWrite | PropsParentRead, locals);
  //props->addParentProps(moduleProps);
  ScopedCfgVar _localProps(props, "__props", new DmiObject(inOf(props)), PropsNoParentWrite);
  
  bool hasScriptVar = props->hasValue("__script");
  ScopedCfgVar _localScript(props, "__script");
  if (hasScriptVar == false)
    _localScript.set(new DmiObject(inOf(script)), PropsNoParentWrite);

  esf->_executionFlags |= ESFFirstStatement;
  //if (ci->getInterfacesCount() > 0 && (ci->interfaces[0]->type->flags & MiCiInterface) == 0)
  int pcount = methinf->getArgumentCount();
  int argssize = args.size();
  if (pcount != argssize)
    THROW1(DmiException, "method called with not matching parameter count");
  int i;

  for (i = 0; i < argssize; ++i)
  {
    int aflags = methinf->methodArgs[i]->flags;
    if (aflags & MiAiOut)
      props->set(methinf->methodArgs[i]->name, new DmiObject(args[i].outOf()), PropsNoParentWrite);
    else
      props->set(methinf->methodArgs[i]->name, new DmiObject(args[i].inOf()), PropsNoParentWrite);
  }
  
  if (Method(ci, methinf).hasMetaAttribute("_cfgscript_defaultArgs") == true)
  {
    RDmiNamedArgArray defaultArgs = (RDmiNamedArgArray)Method(ci, methinf).getMetaAttribute("_cfgscript_defaultArgs")->value;
    for (i = 0; defaultArgs != Nil && i < defaultArgs->length(); ++i)
    {
      props->set(defaultArgs[i]->name, defaultArgs[i]->value, PropsNoParentWrite);
    }
  }
  ASCLITERAL(rest);
  static const ClazzInfo* dminamedClazzInfo = Class::forName("[acdk/lang/dmi/DmiNamedArg")->objectClazzInfo();
  if (argssize > 0 && methinf->methodArgs[argssize - 1]->equalsName(lit_rest) && methinf->methodArgs[argssize - 1]->type == dminamedClazzInfo)
  {
    RDmiNamedArgArray namedRestArgs =  (RDmiNamedArgArray)args[argssize - 1].getObjectVar();
    if (namedRestArgs != Nil)
    {
      for (int i = 0; i < namedRestArgs->length(); ++i)
      {
        props->set(namedRestArgs[i]->name, namedRestArgs[i]->value);
      }
    }

  }
  PEStack stack(script, props, methodsource->begintokenIndex, methodsource->endtokenIndex);
  esf->setScopeProps(props);
  esf->setFrameProps(props);
  //StackedClazzMethodInfo _savemi(script->_currentClazzMethod, methinf);
  if (This != 0)
  {
    props->setObjectVal(lit_this, This, PropsNoParentWrite);
    stack.addUsingVar(lit_this, This);
    
    if (thisobj != Nil && thisobj->_superObject != Nil)
    {
      props->setObjectVal(lit_super, thisobj->_superObject, PropsNoParentWrite);
      stack.addUsingVar(lit_super, thisobj->_superObject);
    }
  }
  stack.addUsingType(clazzinfo); 

  //if (ExecutionStack::get()->calledByConstructor() == true)
  if (flags & MiIvConstructor)
  {
    bool erg = ConstructorMethodParseNode().parseExecute(stack);
    ret = inOf(thisobj);
    if (thisobj->_superObject == Nil && (clazzinfo->flags & MiCiInterface) == 0)
    {
      ScriptVarArray args;
      RStringArray namedargs;
      RString classname = "acdk/lang/acdk::lang::Object";
      ::acdk::lang::dmi::AcdkStdWeakTypeDmiClient dmiclient(stack.props->getCastFlags());
      if (ClazzInfo::findClazzInfo(RString("acdk/lang/Object_DmiProxy")) != 0)
        classname = classname + "_DmiProxy";
      ScriptVar superobj = Object::New(classname, args, namedargs, dmiclient);
      thisobj->setSuperObject(superobj.getObjectVar());
    }
  } 
  else
  {
    //RScript sicScript = Script::getCurrentScript();
    //Script::setCurrentScript(script);
    bool erg = StatementOrPreProc().parseExecute(stack);
    stack.executionFlags &= ~(EFActiveReturn | EFActiveBreak | EFActiveContinue);
    if (stack.isStackEmtpy() == false)
      ret = stack.pop().val.inOf();
    //Script::setCurrentScript(sicScript);
  }
  ExecutionStack::get()->pop(esfIdx);
  return methinf;
}


//static 
bool 
ScriptObject::_isDmiProxyInterface(const ClazzInfo* ci)
{
  if (ci == 0)
    return false;
  if ((ci->flags & MiCiInterface) == MiCiInterface)
    return true;
  if (RString(ci->name)->endsWith("_DmiProxy") == false)
    return false;
  if (ci->getInterfacesCount() < 1)
    return false;
  if ((ci->interfaces[0]->type->flags & MiCiInterface) == MiCiInterface)
    return true;
  return false;
}

/* not working
const ::acdk::lang::dmi::ClazzMethodInfo* 
ScriptObject::delegate_dispatch(
                                                        ::acdk::lang::Object* This, 
                                                         IN(acdk::lang::RString) fname, 
                                                         ::acdk::lang::dmi::ScriptVar& ret, 
                                                         ::acdk::lang::dmi::ScriptVarArray& args, 
                                                         ::acdk::lang::dmi::DmiClient& dc,
                                                         IN(::acdk::lang::RStringArray) namedArgs,
                                                         int flags,
                                                         const ::acdk::lang::dmi::ClazzInfo* clazzinfo,
                                                         const ::acdk::lang::dmi::ClazzMethodInfo* methinf)
{
  const ClazzInfo* ci = clazzinfo;
  Method met(ci, methinf);
  RDmiDelegate delegate =  (RDmiDelegate)met.getObjectMetaAttribute("_cfgscript_delegate");

  return 0;
}
*/

const ::acdk::lang::dmi::ClazzMethodInfo* 
ScriptObject::abstract_method_dispatch(
                                                        ::acdk::lang::Object* This, 
                                                         IN(acdk::lang::RString) fname, 
                                                         ::acdk::lang::dmi::ScriptVar& ret, 
                                                         ::acdk::lang::dmi::ScriptVarArray& args, 
                                                         ::acdk::lang::dmi::DmiClient& dc,
                                                         IN(::acdk::lang::RStringArray) namedArgs,
                                                         int flags,
                                                         const ::acdk::lang::dmi::ClazzInfo* clazzinfo,
                                                         const ::acdk::lang::dmi::ClazzMethodInfo* methinf)
{
  RString className = "";
  if (clazzinfo != 0)
    className = clazzinfo->toTypeString();
  else if (This != 0)
    className = This->getClass()->toString();

  THROW1(NoSuchMethodException, "Call abstract method: " + className + "::" + fname);
  return 0;
}

} // namespace cfgscript
} // namespace acdk