int Mission::checkIntExpr(missionNode *node,int mode){
  int res=0;

    if(node->tag==DTAG_VAR_EXPR){
      res=doIntVar(node,mode);
    }
    else if(node->tag==DTAG_FMATH){
      res=doIMath(node,mode);
    }
    else if(node->tag==DTAG_CONST){
      varInst *vi=doConst(node,mode);
      if(vi && vi->type==VAR_INT){
	res=vi->int_val;
      }
      else{
	fatalError(node,mode,"expected a float const, got a different one");
	assert(0);
      }
      deleteVarInst(vi);
    }
    else if(node->tag==DTAG_CALL){
      varInst *vi=doCall(node,mode);
      if(vi->type==VAR_INT){ 
	res=vi->int_val;
      }
      else if(vi->type==VAR_ANY && mode==SCRIPT_PARSE){
	res=vi->int_val;
      }
      else{
	fatalError(node,mode,"expected a int call, got a different one");
	assert(0);
      }
      deleteVarInst(vi);
    }
    else if(node->tag==DTAG_EXEC){
      varInst *vi=doExec(node,mode);
      if(vi==NULL){
	fatalError(node,mode,"doExec returned NULL");
	assert(0);
      }
      else if(node->script.vartype==VAR_INT){
	res=vi->int_val;
      }
      else{
	fatalError(node,mode,"expected a int exec, got a different one");
	assert(0);
      }
      deleteVarInst(vi);
    }
    else{
      fatalError(node,mode,"no such int expression tag");
      assert(0);
    }

    return res;
}
int Mission::doIMath(missionNode *node,int mode){

  //  debug(0,node,mode,"deprecated Imath");
  varInst *math_vi=doMath(node,mode);

  if(math_vi->type!=VAR_INT){
    fatalError(node,mode,"fmath expected int");
    assert(0);
  }

  int res=math_vi->int_val;
  deleteVarInst(math_vi);

  return res;


#if 0
  //  if(mode==SCRIPT_PARSE){
    string mathname=node->attr_value("math");

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

    int res=checkIntExpr((missionNode *)node->subnodes[0],mode);

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

    for(int i=1;i<len;i++){
      int res2=checkIntExpr((missionNode *)node->subnodes[i],mode);
      if(mode==SCRIPT_RUN){
	if(mathname=="+"){
	  res=res+res2;
	}
	else if(mathname=="-"){
	  res=res-res2;
	}
	else if(mathname=="*"){
	  res=res*res2;
	}
	else if(mathname=="/"){
	  res=res/res2;
	}
	else{
	  fatalError(node,mode,"no such imath expression");
	  assert(0);
	}
      }
    }

    if(mode==SCRIPT_RUN){
      return res;
    }
    return 0;
#endif
}
void Mission::doModule( missionNode *node, int mode )
{
    if (mode == SCRIPT_PARSE) {
        string name = node->attr_value( "name" );
        if (parsemode == PARSE_DECL) {
            if ( name.empty() ) {
                fatalError( node, mode, "you have to give a module name" );
                assert( 0 );
            }
            if (runtime.modules[name] != NULL) {
                fatalError( node, mode, "there can only be one module with name "+name );
                assert( 0 );
            }
            if (name == "director")
                director = node;
            node->script.name = name;

            varInstMap *cvmap = new varInstMap;
            node->script.classvars.push_back( cvmap );
            node->script.classinst_counter = 0;
            debug( 10, node, mode, "created classinst 0" );

            runtime.modules[name] = node;             //add this module to the list of known modules
        }
        scope_stack.push_back( node );

        current_module = node;

        debug( 5, node, mode, "added module "+name+" to list of known modules" );
    }
    if (mode == SCRIPT_RUN) {
        //SCRIPT_RUN
        runtime.cur_thread->module_stack.push_back( node );
        runtime.cur_thread->classid_stack.push_back( 0 );
    }
    vector< easyDomNode* >::const_iterator siter;
    for (siter = node->subnodes.begin(); siter != node->subnodes.end(); siter++) {
        missionNode *snode = (missionNode*) *siter;
        if (snode->tag == DTAG_SCRIPT) {
            varInst *vi = doScript( snode, mode );
            deleteVarInst( vi );
        } else if (snode->tag == DTAG_DEFVAR) {
            doDefVar( snode, mode );
        } else if (snode->tag == DTAG_GLOBALS) {
            doGlobals( snode, mode );
        } else if (snode->tag == DTAG_IMPORT) {
            doImport( snode, mode );
        } else {
            fatalError( snode, mode, "unkown node type for module subnodes" );
            assert( 0 );
        }
    }
    if (mode == SCRIPT_PARSE) {
        scope_stack.pop_back();
    } else {
        runtime.cur_thread->module_stack.pop_back();
        runtime.cur_thread->classid_stack.pop_back();
    }
}
void Mission::removeContextStack()
{
    contextStack *cstack = runtime.cur_thread->exec_stack.back();
    runtime.cur_thread->exec_stack.pop_back();
    if (cstack->return_value != NULL)
        deleteVarInst( cstack->return_value, true );
    delete cstack;
}
void Mission::deleteVarMap( varInstMap *vmap )
{
    vsUMap< string, varInst* >::const_iterator iter;
    for (iter = vmap->begin(); iter != vmap->end(); iter++) {
        varInst *vi = (*iter).second;
        if (vi == NULL)
            debug( 12, NULL, 0, "NULLVAR "+(*iter).first+"\n" );
        else
            deleteVarInst( vi, true );
    }
}
void Mission::removeContext()
{
    contextStack *stack = runtime.cur_thread->exec_stack.back();

    int lastelem = stack->contexts.size()-1;

    scriptContext *old = stack->contexts[lastelem];
    stack->contexts.pop_back();
#if 0
    vsUMap< string, varInst* >::const_iterator iter;
    for (iter = old->varinsts->begin(); iter != old->varinsts->end(); iter++) {
        varInst *vi = (*iter).second;
        deleteVarInst( vi );
    }
#endif
    deleteVarMap( old->varinsts );
    delete old->varinsts;
    delete old;
}
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;
}
bool Mission::doTest(missionNode *node,int mode){
  if(mode==SCRIPT_PARSE){
    string teststr=node->attr_value("test");
    if(teststr.empty()){
      fatalError(node,mode,"you have to give test an argument what to test");
      assert(0);
    }

    if(teststr=="gt"){
      node->script.tester=TEST_GT;
    }
    else if(teststr=="lt"){
      node->script.tester=TEST_LT;
    }
    else if(teststr=="eq"){
      node->script.tester=TEST_EQ;
    }
    else if(teststr=="ne"){
      node->script.tester=TEST_NE;
    }
    else if(teststr=="ge"){
      node->script.tester=TEST_GE;
    }
    else if(teststr=="le"){
      node->script.tester=TEST_LE;
    }
#if 0
    else if(teststr=="between"){
      node->script.tester=TEST_BETWEEN;
    }
#endif
    else {
      fatalError(node,mode,"unknown test argument for test");
      assert(0);
    }

    vector<easyDomNode *>::const_iterator siter;
#if 0
    int i=0;
    for(siter= node->subnodes.begin() ; siter!=node->subnodes.end() && i<2; siter++){
      missionNode *snode=(missionNode *)*siter;
      (node->script.test_arg)[i]=snode;
    }
    if(i<2){
      fatalError(node,mode,"a test-expr needs exact two subnodes");
      assert(0);
    }
#endif

    int len=node->subnodes.size();
    if(len!=2){
      fatalError(node,mode,"a test-expr needs exact two subnodes");
      assert(0);
    }
    
    node->script.test_arg[0]=(missionNode *)node->subnodes[0];
    node->script.test_arg[1]=(missionNode *)node->subnodes[1];

  } // end of parse

    varInst * arg1_vi=checkExpression(node->script.test_arg[0],mode);
    varInst * arg2_vi=checkExpression(node->script.test_arg[1],mode);
    bool res=false;

      if(arg1_vi->type!=arg2_vi->type){
	fatalError(node,mode,"test is getting not the same types");
	assert(0);
      }
      
    if(mode==SCRIPT_RUN){
      if(arg1_vi->type==VAR_FLOAT){
	double arg1=arg1_vi->float_val;
	double arg2=arg2_vi->float_val;

	switch(node->script.tester){
	case TEST_GT:
	  res=(arg1>arg2);
	  break;
	case TEST_LT:
	  res=(arg1<arg2);
	  break;
	case TEST_EQ:
	  res=(arg1==arg2);
	  break;
	case TEST_NE:
	  res=(arg1!=arg2);
	  break;
	case TEST_GE:
	  res=(arg1>=arg2);
	  break;
	case TEST_LE:
	  res=(arg1<=arg2);
	  break;
	default:
	  fatalError(node,mode,"no valid tester");
	  assert(0);
	}
    }
    else if(arg1_vi->type==VAR_INT){
	int arg1=arg1_vi->int_val;
	int arg2=arg2_vi->int_val;

	switch(node->script.tester){
	case TEST_GT:
	  res=(arg1>arg2);
	  break;
	case TEST_LT:
	  res=(arg1<arg2);
	  break;
	case TEST_EQ:
	  res=(arg1==arg2);
	  break;
	case TEST_NE:
	  res=(arg1!=arg2);
	  break;
	case TEST_GE:
	  res=(arg1>=arg2);
	  break;
	case TEST_LE:
	  res=(arg1<=arg2);
	  break;
	default:
	  fatalError(node,mode,"no valid tester");
	  assert(0);
	}
    }
      else{
	fatalError(node,mode,"no such type allowed for test");
	assert(0);
      }
    }// SCRIPT_RUN

    deleteVarInst(arg1_vi);
    deleteVarInst(arg2_vi);

    return res;

}
bool Mission::checkBoolExpr(missionNode *node,int mode){
  bool ok;

  // no difference between parse/run

    if(node->tag==DTAG_AND_EXPR){
      ok=doAndOr(node,mode);
    }
    else if(node->tag==DTAG_OR_EXPR){
      ok=doAndOr(node,mode);
    }
    else if(node->tag==DTAG_NOT_EXPR){
      ok=doNot(node,mode);
    }
    else if(node->tag==DTAG_TEST_EXPR){
      ok=doTest(node,mode);
    }
    else if(node->tag==DTAG_VAR_EXPR){
      ok=doBooleanVar(node,mode);
    }
    else if(node->tag==DTAG_CONST){
      varInst *vi=doConst(node,mode);
      if(vi->type==VAR_BOOL){
	ok=vi->bool_val;
      }
      else{
	fatalError(node,mode,"expected a bool const, got a different one");
	assert(0);
      }
      deleteVarInst(vi);
    }
    else if(node->tag==DTAG_CALL){
      varInst *vi=doCall(node,mode);
      if(vi->type==VAR_BOOL){
	ok=vi->bool_val;
      }
      else if(vi->type==VAR_ANY && mode==SCRIPT_PARSE){
	ok=vi->bool_val;
      }
      else{
	fatalError(node,mode,"expected a bool call, got a different one");
	assert(0);
      }
      deleteVarInst(vi);
    }

    else if(node->tag==DTAG_EXEC){
      varInst *vi=doExec(node,mode);
      if(vi==NULL){
	fatalError(node,mode,"doExec returned NULL");
	assert(0);
 	// parsing?
      }
      else if(node->script.vartype==VAR_BOOL){
	ok=vi->bool_val;
      }
      else{
	fatalError(node,mode,"expected a bool exec, got a different one");
	assert(0);
      }
      deleteVarInst(vi);
    }


    else{
      fatalError(node,mode,"no such boolean expression tag");
      assert(0);
    }

    return ok;
}
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
}