unsigned int Mission::createClassInstance( string modulename )
{
    missionNode *module_node = runtime.modules[modulename];
    if (module_node == NULL) {
        fatalError( NULL, SCRIPT_RUN, "module "+modulename+" not found" );
        assert( 0 );
    }
    module_node->script.classinst_counter++;

    char buf[200];
    sprintf( buf, "class counter for module %s : %d\n", modulename.c_str(), module_node->script.classinst_counter );
    debug( 1, NULL, 0, buf );

    varInstMap *cvmap = new varInstMap();

    module_node->script.classvars.push_back( cvmap );

    varInstMap *cvmap0 = module_node->script.classvars[0];

    vsUMap< string, varInst* >::const_iterator iter;
    for (iter = cvmap0->begin(); iter != cvmap0->end(); iter++) {
        varInst *vi0 = (*iter).second;
        string   vi0_name = (*iter).first;

        varInst *vi  = newVarInst( VI_CLASSVAR );
        vi->type = vi0->type;
        assignVariable( vi, vi0 );

        (*cvmap)[vi0_name] = vi;
    }
    return module_node->script.classinst_counter;
}
varInst *Mission::checkExpression(missionNode *node,int mode){

  varInst *ret=NULL;
  debug(3,node,mode,"checking expression");
  //  printRuntime();

  switch(node->tag){
  case DTAG_AND_EXPR:
  case DTAG_OR_EXPR:
  case DTAG_NOT_EXPR:
  case DTAG_TEST_EXPR:
    {
    bool res=checkBoolExpr(node,mode);
    ret=newVarInst(VI_TEMP);
    ret->type=VAR_BOOL;
    ret->bool_val=res;
    return ret;
    }
    break;
  case DTAG_CONST:
    {
    ret=doConst(node,mode);
    return ret;
    }
    break;
  case DTAG_VAR_EXPR:
    {
    ret=doVariable(node,mode);
    return ret;
    }
    break;
  case DTAG_FMATH:
    {
    ret=doMath(node,mode);
    return ret;
    }
    break;
  case DTAG_CALL:
    {
    ret=doCall(node,mode);
    return ret;
    }
    break;
  case DTAG_EXEC:
    {
    ret=doExec(node,mode);
    return ret;
    }
    break;
  default:
    fatalError(node,mode,"no such expression");
    assert(0);
    break;
  }
  return ret;
}
void Mission::doReturn( missionNode *node, int mode )
{
    trace( node, mode );
    if (mode == SCRIPT_PARSE) {
        missionNode *script = current_script;

        node->script.exec_node = script;
    }
    int len = node->subnodes.size();
    varInst     *vi     = newVarInst( VI_LOCAL );

    missionNode *script = node->script.exec_node;
    if (script->script.vartype == VAR_VOID) {
        if (len != 0) {
            fatalError( node, mode, "script returning void, but return statement with node" );
            assert( 0 );
        }
    } else {
        //return something non-void
        if (len != 1) {
            fatalError( node, mode, "return statement needs only one subnode" );
            assert( 0 );
        }
        missionNode *expr = (missionNode*) node->subnodes[0];
        if (script->script.vartype == VAR_BOOL) {
            bool res = checkBoolExpr( expr, mode );
            vi->bool_val = res;
        } else if (script->script.vartype == VAR_FLOAT) {
            double res = checkFloatExpr( expr, mode );
            vi->float_val = res;
        } else if (script->script.vartype == VAR_INT) {
            int res = checkIntExpr( expr, mode );
            vi->int_val = res;
        } else if (script->script.vartype == VAR_OBJECT) {
            varInst *vi2 = checkObjectExpr( expr, mode );
            vi->type = VAR_OBJECT;
            assignVariable( vi, vi2 );
        } else {
            fatalError( node, mode, "unkown variable type" );
            assert( 0 );
        }
    }
    if (mode == SCRIPT_RUN) {
        contextStack *cstack = runtime.cur_thread->exec_stack.back();

        vi->type = script->script.vartype;

        cstack->return_value = vi;
    }
}
varInst *Mission::call_omap_new(missionNode *node,int mode){
  varInst *viret=newVarInst(VI_TEMP);

    omap_t *my_object=new omap_t;

    viret->type=VAR_OBJECT;
    viret->objectname="omap";
    
    viret->object=(void *)my_object;

    debug(3,node,mode,"omap new object: ");
    printVarInst(3,viret);

    return viret;
}
varInst* Mission::doExec( missionNode *node, int mode )
{
    trace( node, mode );
    if (mode == SCRIPT_PARSE) {
        string name = node->attr_value( "name" );
        if ( name.empty() ) {
            fatalError( node, mode, "you have to give name to exec" );
            assert( 0 );
        }
        node->script.name = name;

        string use_modstr   = node->attr_value( "module" );
        missionNode *module = NULL;
        missionNode *script = NULL;
        if ( !use_modstr.empty() ) {
            module = runtime.modules[use_modstr];
        } else {
            module = current_module;
        }
        if (module == NULL) {
            fatalError( node, mode, "module "+use_modstr+" not found" );
            assert( 0 );
        }
        script = module->script.scripts[name];
        if (script == NULL) {
            fatalError( node, mode, "script "+name+" not found in module "+use_modstr );
            assert( 0 );
        }
        node->script.exec_node   = script;
        node->script.vartype     = script->script.vartype;
        node->script.module_node = module;
    }
    missionNode *arg_node = node->script.exec_node->script.argument_node;

    int nr_arguments;
    if (arg_node == NULL)
        nr_arguments = 0;
    else
        nr_arguments = arg_node->script.nr_arguments;
    int nr_exec_args = node->subnodes.size();
    if (nr_arguments != nr_exec_args) {
        char buffer[200];
        sprintf( buffer, "wrong nr of arguments in doExec=%d doScript=%d", nr_exec_args, nr_arguments );
        fatalError( node, mode, buffer );
        assert( 0 );
    }
    varInstMap *varmap = NULL;
    if (nr_arguments > 0) {
        varmap = new varInstMap;
        for (int i = 0; i < nr_arguments; i++) {
            missionNode *defnode  = (missionNode*) arg_node->subnodes[i];
            missionNode *callnode = (missionNode*) node->subnodes[i];

            varInst     *vi = newVarInst( VI_LOCAL );
            vi->type = defnode->script.vartype;
            if (defnode->script.vartype == VAR_FLOAT) {
                debug( 4, node, mode, "doExec checking floatExpr" );
                double res = checkFloatExpr( callnode, mode );
                vi->float_val = res;
            } else if (defnode->script.vartype == VAR_INT) {
                debug( 4, node, mode, "doExec checking intExpr" );
                int res = checkIntExpr( callnode, mode );
                vi->int_val = res;
            } else if (defnode->script.vartype == VAR_BOOL) {
                debug( 4, node, mode, "doExec checking boolExpr" );
                bool ok = checkBoolExpr( callnode, mode );
                vi->bool_val = ok;
            } else if (defnode->script.vartype == VAR_OBJECT) {
                debug( 3, node, mode, "doExec checking objectExpr" );
                varInst *ovi = checkObjectExpr( callnode, mode );
                vi->type = VAR_OBJECT;
                if (mode == SCRIPT_RUN)
                    assignVariable( vi, ovi );
                deleteVarInst( ovi );
            } else {
                fatalError( node, mode, "unsupported vartype in doExec" );
                assert( 0 );
            }
            (*varmap)[defnode->script.name] = vi;
        }
    }
    if (mode == SCRIPT_RUN) {
        //SCRIPT_RUN

        debug( 4, node, mode, "executing "+node->script.name );

        missionNode *module     = node->script.module_node;

        missionNode *old_module = runtime.cur_thread->module_stack.back();

        unsigned int classid    = 0;
        if (old_module == module)
            classid = runtime.cur_thread->classid_stack.back();
        runtime.cur_thread->module_stack.push_back( module );
        runtime.cur_thread->classid_stack.push_back( classid );

        varInst *vi = doScript( node->script.exec_node, mode, varmap );

        runtime.cur_thread->module_stack.pop_back();
        runtime.cur_thread->classid_stack.pop_back();
        if (varmap) {
            deleteVarMap( varmap );
            delete varmap;
        }
        return vi;
    }
    //SCRIPT_PARSE

    varInst *vi = newVarInst( VI_TEMP );

    vi->type = node->script.exec_node->script.vartype;

    return vi;
}
varInst* Mission::doScript( missionNode *node, int mode, varInstMap *varmap )
{
    trace( node, mode );
    if (mode == SCRIPT_PARSE) {
        current_script = node;
        if (parsemode == PARSE_DECL) {
            node->script.name = node->attr_value( "name" );
            if ( node->script.name.empty() )
                fatalError( node, mode, "you have to give a script name" );
            current_module->script.scripts[node->script.name] = node;
            debug( 5, node, mode, "added to module "+current_module->script.name+" : script ="+node->script.name );

            node->script.nr_arguments = 0;

            string retvalue = node->attr_value( "type" );
            if (retvalue.empty() || retvalue == "void")
                node->script.vartype = VAR_VOID;
            else
                node->script.vartype = vartypeFromString( retvalue );
        }
        scope_stack.push_back( node );
    }
    debug( 5, node, mode, "executing script name="+node->script.name );
    if (mode == SCRIPT_RUN) {
        addContextStack( node );
        addContext( node );
    }
    vector< easyDomNode* >::const_iterator siter;
    if (mode == SCRIPT_PARSE && parsemode == PARSE_DECL) {
        node->script.nr_arguments  = 0;
        node->script.argument_node = NULL;
    }
    for (siter = node->subnodes.begin(); siter != node->subnodes.end() && !have_return( mode ); siter++) {
        missionNode *snode = (missionNode*) *siter;
        if (snode->tag == DTAG_ARGUMENTS) {
            doArguments( snode, mode, varmap );
            if (mode == SCRIPT_PARSE && parsemode == PARSE_DECL)
                node->script.argument_node = snode;
            char buffer[200];
            sprintf( buffer, "nr of arguments=%d", node->script.nr_arguments );
            debug( 3, node, mode, buffer );
        } else {
            if (mode == SCRIPT_PARSE && parsemode == PARSE_DECL) {
                //do nothing, break here
            } else {
                checkStatement( snode, mode );
            }
        }
    }
    if (mode == SCRIPT_RUN) {
        removeContext();
        contextStack *cstack = runtime.cur_thread->exec_stack.back();
        varInst *vi = cstack->return_value;
        if (vi != NULL) {
            if (node->script.vartype != vi->type) {
                fatalError( node, mode, "doScript: return type not set correctly" );
                assert( 0 );
            }
        } else
        if (node->script.vartype != VAR_VOID) {
            fatalError( node, mode, "no return set from doScript" );
            assert( 0 );
        }
        varInst *viret = NULL;
        if (vi) {
            viret = newVarInst( VI_TEMP );
            viret->type = vi->type;
            assignVariable( viret, vi );
        }
        removeContextStack();

        return viret;
    } else {
        scope_stack.pop_back();
        return NULL;
    }
}
varInst * Mission::doMath(missionNode *node,int mode){
  //  if(mode==SCRIPT_PARSE){
    string mathname=node->attr_value("math");

    int len=node->subnodes.size();
    if(len<2){
      fatalError(node,mode,"math needs at least 2 arguments");
      assert(0);
    }

    varInst *res_vi=newVarInst(VI_TEMP);

    varInst* res1_vi=checkExpression((missionNode *)node->subnodes[0],mode);

    if(res1_vi->type!=VAR_INT && res1_vi->type!=VAR_FLOAT && res1_vi->type!=VAR_ANY){
      printf("res1_vi=%d\n",res1_vi->type);
      fatalError(node,mode,"only int or float expr allowed for math");
      assert(0);
    }
    res_vi->type=res1_vi->type;
    assignVariable(res_vi,res1_vi);
    if(res_vi->type==VAR_ANY){
      res_vi->type=VAR_FLOAT;
    }
    deleteVarInst(res1_vi);

    //    char buffer[200];
    //sprintf(buffer,"fmath: 1st expr returns %f",res);
    //debug(4,node,mode,buffer);

    for(int i=1;i<len;i++){
      varInst * res2_vi=checkExpression((missionNode *)node->subnodes[i],mode);
      var_type res2_type=res2_vi->type;

      if(res2_type==VAR_INT && res_vi->type==VAR_FLOAT){
	res2_type=VAR_FLOAT;
	if(mode==SCRIPT_RUN){
	  float res2=(float)res2_vi->int_val;
	  float res=floatMath(mathname,res_vi->float_val,res2);
	  res_vi->float_val=res;
	}
      }
     else if(res2_type==VAR_FLOAT && res_vi->type==VAR_INT){
       res_vi->type=VAR_FLOAT;
       if(mode==SCRIPT_RUN){
	 res_vi->float_val=(float)res_vi->int_val;
	 float res2=res2_vi->float_val;
	 float res=floatMath(mathname,res_vi->float_val,res2);
	 res_vi->float_val=res;
       }
     }
      else{
	if(res_vi->type!=res2_type){
	  fatalError(node,mode,"can't do math on such types");
	  assert(0);
	}
	if(mode==SCRIPT_RUN){
	  if(res_vi->type==VAR_INT){
	    int res=intMath(mathname,res_vi->int_val,res2_vi->int_val);
	    res_vi->int_val=res;
	  }
	  else if(res_vi->type==VAR_FLOAT){
	    float res=floatMath(mathname,res_vi->float_val,res2_vi->float_val);
	    res_vi->float_val=res;
	  }
	  else{
	    if(res_vi->type!=res2_type){
	      fatalError(node,mode,"can't do math on such types");
	      assert(0);
	    }
	  }
	} // of SCRIPT_RUN
      } // else
      deleteVarInst(res2_vi);
    } // for arguments

    return res_vi;
}
varInst *Mission::call_omap(missionNode *node,int mode){

  //varInst *viret=new varInst;
  varInst *viret=NULL;

  if(mode==SCRIPT_PARSE){
    string cmd=node->attr_value("name");
    node->script.method_id=module_omap_map[cmd];
  }

   callback_module_omap_type method_id=(callback_module_omap_type) node->script.method_id;


  if(method_id==CMT_OMAP_new){
    
    viret=call_omap_new(node,mode);

    return viret;
  }
  else{
    varInst *ovi=getObjectArg(node,mode);
    omap_t *my_object=getOMapObject(node,mode,ovi);

    if(method_id==CMT_OMAP_delete){
      if(mode==SCRIPT_RUN){

	omap_t::iterator iter;

	for(iter=my_object->begin();iter!=my_object->end();iter++){
	  string varname=(*iter).first ;
	  varInst *vi=(*iter).second;
	  deleteVarInst(vi,true);
	}
	my_object->clear();
	delete my_object;
      }
      viret=newVarInst(VI_TEMP);
      viret->type=VAR_VOID;
    }
    else if(method_id==CMT_OMAP_set){
      missionNode *snode=getArgument(node,mode,2);
      //varInst *vi=doVariable(snode,mode); // should be getObjExpr
      varInst *var_vi=checkExpression(snode,mode); // should be getObjExpr
      
      string name=getStringArgument(node,mode,1);

      debug(3,node,mode,"omap set");

      if(mode==SCRIPT_RUN){
	varInst *push_vi=newVarInst(VI_IN_OBJECT);
	push_vi->type=var_vi->type;
	assignVariable(push_vi,var_vi);

	(*my_object)[name]=push_vi;
	//printf("setting [%s] type %d\n",name.c_str(),push_vi->type);
      }

      deleteVarInst(var_vi);
      viret=newVarInst(VI_TEMP);
      viret->type=VAR_VOID;
      //return viret;
    }
    else if(method_id==CMT_OMAP_get){
      debug(3,node,mode,"omap.get");

      string name=getStringArgument(node,mode,1);

      viret=newVarInst(VI_TEMP);
      viret->type=VAR_ANY;

      if(mode==SCRIPT_RUN){
	varInst *back_vi=(*my_object)[name];
	assignVariable(viret,back_vi);
	//	printf("viret type=%d back_vi type=%d\n",viret->type,back_vi->type);
	if(back_vi->type>10){
	  assert(0);
	}
	deleteVarInst(back_vi); // this won't delete it
      }
    }
    else if(method_id==CMT_OMAP_toxml){
      if(node->subnodes.size()!=1){
	fatalError(node,mode,"olist.toxml needs no arguments");
	assert(0);
      }

      debug(3,node,mode,"omap.toxml");

      if(mode==SCRIPT_RUN){
	//call_olist_toxml(node,mode,ovi);
      }

      viret =newVarInst(VI_TEMP);
      viret->type=VAR_VOID;
    }
    else if(method_id==CMT_OMAP_size){
      if(node->subnodes.size()!=1){
	fatalError(node,mode,"olist.size needs one arguments");
	assert(0);
      }

      debug(3,node,mode,"omap.size");

      viret=newVarInst(VI_TEMP);

      if(mode==SCRIPT_RUN){
	int len=my_object->size();
	viret->int_val=len;
      }

      viret->type=VAR_INT;
      //return viret;
    }
    else{
      fatalError(node,mode,"unknown command "+node->script.name+" for callback omap");
      assert(0);
    }
    
    deleteVarInst(ovi);
    return viret;
  } // else (objects)

  return NULL; // never reach
}