 #include "translate.h"
 #include "syntax.h"
 #include "arch.h"
 #include "symbol.h"
 #include "error.h"
 #include <stdio.h>
 #include "so.h"
 #define TR_GFID(x) (x)
 #define TR_GSID(x) (x)
 #define TR_GRID(x) (x)
/* just for debug! */
static FILE *OUT = NULL;
BOOL interpret_generated(struct ReactCxt *rc,
                         LmnRule rule,
                         LmnRuleInstr instr)
{
  LmnInstrOp op;
  /* just for debug! */
  if(! OUT){
    /* out = stderr; */
    OUT = stdout;
    /* OUT = fopen("/dev/null", "w"); */
  }
  while (TRUE) {
  /* LOOP:; */
    READ_VAL(LmnInstrOp, instr, op);
    switch (op) {
case INSTR_SPEC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  TR_INSTR_SPEC(targ1);
  break;
}
case INSTR_INSERTCONNECTORSINNULL:{
  LmnInstrVar targ0;
  LmnWord *targ1;
  int targ1_num;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL_LIST(instr, targ1);
  {
    const Vector v = vec_const_temporary_from_array(targ1_num, targ1);
    wt[targ0] = (LmnWord)insertconnectors(NULL, &v);
    if (RC_GET_MODE(rc, REACT_ND)) { at[targ0] = 0; /* MC */ }
  }
  free(targ1);
  break;
}
case INSTR_INSERTCONNECTORS:{
  LmnInstrVar targ0;
  LmnWord *targ1;
  int targ1_num;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL_LIST(instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  {
    const Vector v = vec_const_temporary_from_array(targ1_num, targ1);
    wt[targ0] = (LmnWord)insertconnectors((LmnMembrane *)wt[targ2] , &v);
    if (RC_GET_MODE(rc, REACT_ND)) { at[targ0] = 0; /* MC */ }
  }
  free(targ1);
  break;
}
case INSTR_COMMIT:{
  lmn_interned_str targ0;
  LmnLineNum targ1;
  READ_VAL(lmn_interned_str, instr, targ0);
  READ_VAL(LmnLineNum, instr, targ1);
  {
    LmnMembrane *ptmp_global_root;
    LmnWord *pwt_temp;
    LmnByte *pat_temp;
    tr_instr_commit_ready(rc, rule, TR_GSID(targ0), targ1, &ptmp_global_root, &pwt_temp, &pat_temp);
  }
  break;
}
case INSTR_FINDATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnLinkAttr targ2_attr;
  union LmnFunctorLiteral targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL_FUNC(instr, targ2);
  if(LMN_ATTR_IS_DATA(targ2_attr)){
    fprintf(stderr, "I can not find data atoms.\n");
    assert(FALSE);
  }else{
    {
      AtomListEntry *atomlist_ent = lmn_mem_get_atomlist((LmnMembrane*)wt[targ1], TR_GFID(targ2.functor_data));
      LmnSAtom atom;
  
      if (atomlist_ent) {
        at[targ0] = LMN_ATTR_MAKE_LINK(0);
        /* EACH_ATOMを使うとループ内コード中でコンマが使えない場合が出てくる */
        for(atom = atomlist_head(atomlist_ent);
            atom != lmn_atomlist_end(atomlist_ent);
            atom = LMN_SATOM_GET_NEXT_RAW(atom)){
          if(LMN_SATOM_GET_FUNCTOR(atom) != LMN_RESUME_FUNCTOR){
            wt[targ0] = (LmnWord)atom;
          }
        }
      }
    }
    return FALSE;
  }
  break;
}
case INSTR_LOCKMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  lmn_interned_str targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(lmn_interned_str, instr, targ2);
  wt[targ0] = (LmnWord)LMN_PROXY_GET_MEM(wt[targ1]);
  if (RC_GET_MODE(rc, REACT_ND)) { at[targ0] = 0; /* MC */ }
  if(((LmnMembrane*)wt[targ0])->name != TR_GSID(targ2)) return FALSE;
  break;
}
case INSTR_ANYMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  lmn_interned_str targ3;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  READ_VAL(lmn_interned_str, instr, targ3);
  {
    LmnMembrane *mp = ((LmnMembrane*)wt[targ1])->child_head;
    for (; mp; mp=mp->next) {
      wt[targ0] = (LmnWord)mp;
      if (RC_GET_MODE(rc, REACT_ND)) { at[targ0] = 0; /* MC */ }
      if (mp->name == TR_GSID(targ3)){
      }
    }
    return FALSE;
  }
  break;
}
case INSTR_NMEMS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!lmn_mem_nmems((LmnMembrane*)wt[targ0], targ1)) return FALSE;
  break;
}
case INSTR_NORULES:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if(((LmnMembrane *)wt[targ0])->rulesets.num) return FALSE;
  break;
}
case INSTR_NEWATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnLinkAttr targ2_attr;
  union LmnFunctorLiteral targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL_FUNC(instr, targ2);
  switch(targ2_attr){
  case LMN_INT_ATTR:
    wt[targ0] = targ2.long_data;
    break;
  case LMN_DBL_ATTR:
    wt[targ0] = (LmnWord)LMN_MALLOC(double);
    *(double*)wt[targ0] = targ2.double_data;
    break;
  case LMN_STRING_ATTR:
    wt[targ0] = (LmnWord)lmn_string_make(lmn_id_to_name(TR_GSID(targ2.string_data)));
    break;
  default:
    wt[targ0] = LMN_ATOM(lmn_new_atom(TR_GFID(targ2.functor_data)));
    break;
  }
    at[targ0] = targ2_attr;
  lmn_mem_push_atom((LmnMembrane*)wt[targ1], wt[targ0], targ2_attr);
  break;
}
case INSTR_NATOMS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!lmn_mem_natoms((LmnMembrane*)wt[targ0], targ1)) return FALSE;
  break;
}
case INSTR_NATOMSINDIRECT:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!lmn_mem_natoms((LmnMembrane*)wt[targ0], wt[targ1])) return FALSE;
  break;
}
case INSTR_ALLOCLINK:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  TR_INSTR_ALLOCLINK(targ0, targ1, targ2);
  break;
}
case INSTR_UNIFYLINKS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  TR_INSTR_UNIFYLINKS(targ0, targ1, targ2);
  break;
}
case INSTR_NEWLINK:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  LmnInstrVar targ3;
  LmnInstrVar targ4;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  READ_VAL(LmnInstrVar, instr, targ3);
  READ_VAL(LmnInstrVar, instr, targ4);
  lmn_mem_newlink((LmnMembrane *)wt[targ4], wt[targ0], at[targ0], targ1, wt[targ2], at[targ2], targ3);
  break;
}
case INSTR_RELINK:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  LmnInstrVar targ3;
  LmnInstrVar targ4;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  READ_VAL(LmnInstrVar, instr, targ3);
  READ_VAL(LmnInstrVar, instr, targ4);
  TR_INSTR_RELINK(targ0, targ1, targ2, targ3, targ4);
  break;
}
case INSTR_GETLINK:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = LMN_SATOM_GET_LINK(wt[targ1], targ2);
  at[targ0] = LMN_SATOM_GET_ATTR(wt[targ1], targ2);
  break;
}
case INSTR_UNIFY:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  LmnInstrVar targ3;
  LmnInstrVar targ4;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  READ_VAL(LmnInstrVar, instr, targ3);
  READ_VAL(LmnInstrVar, instr, targ4);
  lmn_mem_unify_atom_args((LmnMembrane *)wt[targ4], LMN_SATOM(wt[targ0]), targ1, LMN_SATOM(wt[targ2]), targ3);
  break;
}
case INSTR_PROCEED:{
  return TRUE;
  break;
}
case INSTR_STOP:{
  return FALSE;
  break;
}
case INSTR_NOT:{
  LmnSubInstrSize targ0;
  READ_VAL(LmnSubInstrSize, instr, targ0);
  { /* not */
  }
  break;
}
case INSTR_ENQUEUEATOM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  break;
}
case INSTR_DEQUEUEATOM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  break;
}
case INSTR_NEWMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  {
    LmnMembrane *mp = lmn_mem_make();
    lmn_mem_add_child_mem((LmnMembrane*)wt[targ1], mp);
    wt[targ0] = (LmnWord)mp;
    lmn_mem_set_active(mp, TRUE);
    if (RC_GET_MODE(rc, REACT_MEM_ORIENTED)) {
      lmn_memstack_push(RC_MEMSTACK(rc), mp);
    }
  }
  break;
}
case INSTR_ALLOCMEM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  wt[targ0] = (LmnWord)lmn_mem_make();
  break;
}
case INSTR_REMOVEATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  lmn_mem_remove_atom((LmnMembrane*)wt[targ1], wt[targ0], at[targ0]);
  break;
}
case INSTR_FREEATOM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  lmn_free_atom(wt[targ0], at[targ0]);
  break;
}
case INSTR_REMOVEMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  lmn_mem_remove_mem((LmnMembrane *)wt[targ1], (LmnMembrane *)wt[targ0]);
  break;
}
case INSTR_FREEMEM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  lmn_mem_free((LmnMembrane*)wt[targ0]);
  break;
}
case INSTR_ADDMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  lmn_mem_add_child_mem((LmnMembrane *)wt[targ0], (LmnMembrane *)wt[targ1]);
  break;
}
case INSTR_ENQUEUEMEM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if (RC_GET_MODE(rc, REACT_ND)) {
    activate_ancestors((LmnMembrane *)wt[targ0]); /* MC */
  } else if (RC_GET_MODE(rc, REACT_MEM_ORIENTED)) {
    lmn_memstack_push(RC_MEMSTACK(rc), (LmnMembrane *)wt[targ0]); /* 通常実行時 */
  }
  break;
}
case INSTR_UNLOCKMEM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  break;
}
case INSTR_LOADRULESET:{
  LmnInstrVar targ0;
  LmnRulesetId targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnRulesetId, instr, targ1);
  lmn_mem_add_ruleset((LmnMembrane*)wt[targ0], lmn_ruleset_from_id(TR_GRID(targ1)));
  break;
}
case INSTR_LOADMODULE:{
  LmnInstrVar targ0;
  lmn_interned_str targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(lmn_interned_str, instr, targ1);
  {
    LmnRuleSet ruleset;
    if ((ruleset = lmn_get_module_ruleset(TR_GSID(targ1)))) {
      lmn_mem_add_ruleset((LmnMembrane*)wt[targ0], ruleset);
    } else {
      fprintf(stderr, "Undefined module %s\n", lmn_id_to_name(TR_GSID(targ1)));
    }
  }
  break;
}
case INSTR_RECURSIVELOCK:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  break;
}
case INSTR_RECURSIVEUNLOCK:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  break;
}
case INSTR_DEREFATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)LMN_SATOM(LMN_SATOM_GET_LINK(wt[targ1], targ2));
  at[targ0] = LMN_SATOM_GET_ATTR(wt[targ1], targ2);
  break;
}
case INSTR_DEREF:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  LmnInstrVar targ3;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  READ_VAL(LmnInstrVar, instr, targ3);
  {
    LmnByte attr = LMN_SATOM_GET_ATTR(wt[targ1], targ2);
    if (LMN_ATTR_IS_DATA(attr)) {
      if (targ3 != 0) return FALSE;
    } else {
      if (attr != targ3) return FALSE;
    }
    wt[targ0] = LMN_SATOM_GET_LINK(wt[targ1], targ2);
    at[targ0] = attr;
  }
  break;
}
case INSTR_FUNC:{
  LmnInstrVar targ0;
  LmnLinkAttr targ1_attr;
  union LmnFunctorLiteral targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL_FUNC(instr, targ1);
  if(LMN_ATTR_IS_DATA(targ1_attr)){
    if(LMN_ATTR_IS_DATA(at[targ0]) && at[targ0]==targ1_attr){
      switch(targ1_attr){
      case LMN_INT_ATTR:
        if(wt[targ0] != targ1.long_data) return FALSE;
        break;
      case LMN_DBL_ATTR:
        if(*(double*)wt[targ0] != targ1.double_data) return FALSE;
        break;
      case LMN_STRING_ATTR: {
        LmnString s = lmn_string_make(lmn_id_to_name(TR_GSID(targ1.string_data)));
        if(! lmn_string_eq(s, (LmnString)wt[targ0])) return FALSE;
        lmn_string_free(s);
        fprintf(stderr, "string attr is not implemented.");
        break;
      }
      default:
        lmn_fatal("implementation error");
      }
    }else{
      return FALSE;
    }
  }else{
    if(LMN_ATTR_IS_DATA(at[targ0]) ||
       LMN_SATOM_GET_FUNCTOR(LMN_SATOM(wt[targ0])) != TR_GFID(targ1.functor_data)) return FALSE;
  }
  break;
}
case INSTR_NOTFUNC:{
  LmnInstrVar targ0;
  LmnLinkAttr targ1_attr;
  union LmnFunctorLiteral targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL_FUNC(instr, targ1);
  if(LMN_ATTR_IS_DATA(targ1_attr)){
    if(! (LMN_ATTR_IS_DATA(at[targ0]) && at[targ0]==targ1_attr)){
      switch(targ1_attr){
      case LMN_INT_ATTR:
        if(wt[targ0] == targ1.long_data) return FALSE;
        break;
      case LMN_DBL_ATTR:
        if(*(double*)wt[targ0] == targ1.double_data) return FALSE;
        fprintf(stderr, "double attr is not implemented.");
        break;
      case LMN_STRING_ATTR: {
        LmnString s = lmn_string_make(lmn_id_to_name(TR_GSID(targ1.string_data)));
        if(lmn_string_eq(s, (LmnString)wt[targ0])) return FALSE;
        lmn_string_free(s);
        fprintf(stderr, "string attr is not implemented.");
        break;
      }
      default:
        lmn_fatal("implementation error");
      }
    }
  }else{
    if(! (LMN_ATTR_IS_DATA(at[targ0]) ||
          LMN_SATOM_GET_FUNCTOR(LMN_SATOM(wt[targ0])) != TR_GFID(targ1.functor_data))) return FALSE;
  }
  break;
}
case INSTR_ISGROUND:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  {
    Vector *srcvec = links_from_idxs((Vector *)wt[targ1], wt, at);
    Vector *avovec = links_from_idxs((Vector *)wt[targ2], wt, at);
    unsigned long natoms;
    BOOL b = lmn_mem_is_ground(srcvec, avovec, &natoms);
    
    free_links(srcvec);
    free_links(avovec);
    if(! b) return FALSE;
    wt[targ0] = (LmnWord)natoms;
    at[targ0] = LMN_INT_ATTR;
  }
  break;
}
case INSTR_ISUNARY:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if (LMN_ATTR_IS_DATA(at[targ0])) {
    switch (at[targ0]) {
    case LMN_SP_ATOM_ATTR:
      if (!SP_ATOM_IS_GROUND(wt[targ0])) return FALSE;
      break;
    default:
      break;
    }
  } else if (LMN_SATOM_GET_ARITY(wt[targ0]) != 1){
    return FALSE;
  }
  break;
}
case INSTR_ISINT:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if(at[targ0] != LMN_INT_ATTR) return FALSE;
  break;
}
case INSTR_ISFLOAT:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if(at[targ0] != LMN_DBL_ATTR) return FALSE;
  break;
}
case INSTR_ISSTRING:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if(! lmn_is_string(wt[targ0], at[targ0])) return FALSE;
  break;
}
case INSTR_ISINTFUNC:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if(at[targ0] != LMN_INT_ATTR) return FALSE;
  break;
}
case INSTR_ISFLOATFUNC:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if(at[targ0] != LMN_DBL_ATTR) return FALSE;
  break;
}
case INSTR_COPYATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  at[targ0] = at[targ2];
  wt[targ0] = lmn_copy_atom(wt[targ2], at[targ2]);
  lmn_mem_push_atom((LmnMembrane *)wt[targ1], wt[targ0], at[targ0]);
  break;
}
case INSTR_EQATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (LMN_ATTR_IS_DATA(at[targ0]) ||
      LMN_ATTR_IS_DATA(at[targ1]) ||
      LMN_SATOM(wt[targ0]) != LMN_SATOM(wt[targ1])) return FALSE;
  break;
}
case INSTR_NEQATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (!(LMN_ATTR_IS_DATA(at[targ0]) ||
        LMN_ATTR_IS_DATA(at[targ1]) ||
        LMN_SATOM(wt[targ0]) != LMN_SATOM(wt[targ1]))) return FALSE;
  break;
}
case INSTR_EQMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(wt[targ0] != wt[targ1]) return FALSE;
  break;
}
case INSTR_NEQMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(wt[targ0] == wt[targ1]) return FALSE;
  break;
}
case INSTR_NEWLIST:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  {
    Vector *listvec = vec_make(16);
    wt[targ0] = (LmnWord)listvec;
    if (RC_GET_MODE(rc, REACT_ND)) { at[targ0] = 0; /* MC */ }
  }
  break;
}
case INSTR_ADDTOLIST:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  vec_push((Vector *)wt[targ0], targ1);
  break;
}
case INSTR_GETFROMLIST:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  switch (at[targ1]) {
    case LIST_AND_MAP:
      wt[targ0] = vec_get((Vector *)wt[targ1], (unsigned int)targ2);
      if (targ2 == 0){
        at[targ0] = LINK_LIST;
      }else if (targ2 == 1){
        at[targ0] = MAP;
      }else{
        assert(0);
      }
      break;
    case LINK_LIST: /* LinkObjをfreeするのはここ？ */
    {
      LinkObj lo = (LinkObj)vec_get((Vector *)wt[targ1], (unsigned int)targ2);
      wt[targ0] = (LmnWord)lo->ap;
      at[targ0] = lo->pos;
      break;
    }
  }
  break;
}
case INSTR_EQGROUND:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  {
    Vector *srcvec = links_from_idxs((Vector*)wt[targ0], wt, at);
    Vector *dstvec = links_from_idxs((Vector*)wt[targ1], wt, at);
    BOOL same = lmn_mem_cmp_ground(srcvec, dstvec);
    free_links(srcvec);
    free_links(dstvec);
    if(! same) return FALSE;
  }
  break;
}
case INSTR_NEQGROUND:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  {
    Vector *srcvec = links_from_idxs((Vector*)wt[targ0], wt, at);
    Vector *dstvec = links_from_idxs((Vector*)wt[targ1], wt, at);
    BOOL same = lmn_mem_cmp_ground(srcvec, dstvec);
    free_links(srcvec);
    free_links(dstvec);
    if(same) return FALSE;
  }
  break;
}
case INSTR_COPYGROUND:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  {
    Vector *srcvec = links_from_idxs((Vector*)wt[targ1], wt, at);
    Vector *dstlovec, *retvec;
    ProcessTbl atommap;
    
    lmn_mem_copy_ground((LmnMembrane*)wt[targ2], srcvec, &dstlovec, &atommap);
    free_links(srcvec);
    
    /* 返り値の作成 */
    retvec = vec_make(2);
    vec_push(retvec, (LmnWord)dstlovec);
    vec_push(retvec, (LmnWord)atommap);
    wt[targ0] = (LmnWord)retvec;
    at[targ0] = (LmnByte)LIST_AND_MAP;
  }
  break;
}
case INSTR_REMOVEGROUND:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  {
    Vector *srcvec = links_from_idxs((Vector*)wt[targ0], wt, at);
    lmn_mem_remove_ground((LmnMembrane*)wt[targ1], srcvec);
    free_links(srcvec);
  }
  break;
}
case INSTR_FREEGROUND:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  {
    Vector *srcvec = links_from_idxs((Vector*)wt[targ0], wt, at);
    lmn_mem_free_ground(srcvec);
    free_links(srcvec);
  }
  break;
}
case INSTR_STABLE:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  if (lmn_mem_is_active((LmnMembrane *)wt[targ0])) return FALSE;
  break;
}
case INSTR_IADD:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] + (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_ISUB:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] - (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IMUL:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] * (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IDIV:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] / (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_INEG:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  wt[targ0] = (LmnWord)(-(long)wt[targ1]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IMOD:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] % (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_INOT:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)(~(long)wt[targ1]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IAND:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] & (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IOR:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] | (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IXOR:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)((long)wt[targ1] ^ (long)wt[targ2]);
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_ILT:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] < (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_ILE:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] <= (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_IGT:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] > (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_IGE:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] >= (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_IEQ:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] == (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_INE:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] != (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_ILTFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] < (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_ILEFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] <= (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_IGTFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] > (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_IGEFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!((long)wt[targ0] >= (long)wt[targ1])) return FALSE;
  break;
}
case INSTR_FADD:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)LMN_MALLOC(double);
  *(double *)wt[targ0] = *(double *)wt[targ1] + *(double *)wt[targ2];
  at[targ0] = LMN_DBL_ATTR;
  break;
}
case INSTR_FSUB:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)LMN_MALLOC(double);
  *(double *)wt[targ0] = *(double *)wt[targ1] - *(double *)wt[targ2];
  at[targ0] = LMN_DBL_ATTR;
  break;
}
case INSTR_FMUL:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)LMN_MALLOC(double);
  *(double *)wt[targ0] = *(double *)wt[targ1] * *(double *)wt[targ2];
  at[targ0] = LMN_DBL_ATTR;
  break;
}
case INSTR_FDIV:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)LMN_MALLOC(double);
  *(double *)wt[targ0] = *(double *)wt[targ1] / *(double *)wt[targ2];
  at[targ0] = LMN_DBL_ATTR;
  break;
}
case INSTR_FNEG:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  wt[targ0] = (LmnWord)LMN_MALLOC(double);
  *(double *)wt[targ0] = -*(double *)wt[targ1];
  at[targ0] = LMN_DBL_ATTR;
  break;
}
case INSTR_FLT:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!(*(double*)wt[targ0] < *(double*)wt[targ1])) return FALSE;
  break;
}
case INSTR_FLE:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!(*(double*)wt[targ0] <= *(double*)wt[targ1])) return FALSE;
  break;
}
case INSTR_FGT:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!(*(double*)wt[targ0] > *(double*)wt[targ1])) return FALSE;
  break;
}
case INSTR_FGE:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!(*(double*)wt[targ0] >= *(double*)wt[targ1])) return FALSE;
  break;
}
case INSTR_FEQ:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!(*(double*)wt[targ0] == *(double*)wt[targ1])) return FALSE;
  break;
}
case INSTR_FNE:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(!(*(double*)wt[targ0] != *(double*)wt[targ1])) return FALSE;
  break;
}
case INSTR_ALLOCATOM:{
  LmnInstrVar targ0;
  LmnLinkAttr targ1_attr;
  union LmnFunctorLiteral targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL_FUNC(instr, targ1);
  switch(targ1_attr){
  case LMN_INT_ATTR:
    wt[targ0] = targ1.long_data;
    at[targ0] = LMN_INT_ATTR;
    break;    
  case LMN_DBL_ATTR:
    {
  /* 困った */
    }
    break;
  case LMN_STRING_ATTR:
    wt[targ0] = targ1.string_data;
    at[targ0] = LMN_CONST_STR_ATTR;
    break;
  default:
    lmn_fatal("Implementation error");
  }
  break;
}
case INSTR_ALLOCATOMINDIRECT:{
  LmnInstrVar targ0;
  LmnFunctor targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnFunctor, instr, targ1);
  if (LMN_ATTR_IS_DATA(at[targ1])) {
    wt[targ0] = lmn_copy_data_atom(wt[targ1], at[targ1]);
    at[targ0] = at[targ1];
  } else { /* symbol atom */
    fprintf(stderr, "symbol atom can't be created in GUARD\n");
    exit(EXIT_FAILURE);
  }
  break;
}
case INSTR_SAMEFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (!lmn_eq_func(wt[targ0], at[targ0], wt[targ1], at[targ1])) return FALSE;
  break;
}
case INSTR_GETFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if(LMN_ATTR_IS_DATA(at[targ1])){
    wt[targ0] = wt[targ1];
  }else{
    wt[targ0] = (LmnWord)LMN_SATOM_GET_FUNCTOR(wt[targ1]);
  }
  at[targ0] = at[targ1];
  break;
}
case INSTR_SETMEMNAME:{
  LmnInstrVar targ0;
  lmn_interned_str targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(lmn_interned_str, instr, targ1);
  ((LmnMembrane *)wt[targ0])->name = TR_GSID(targ1);
  break;
}
case INSTR_COPYRULES:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  TR_INSTR_COPYRULES(targ0, targ1);
  break;
}
case INSTR_REMOVEPROXIES:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  lmn_mem_remove_proxies((LmnMembrane *)wt[targ0]);
  break;
}
case INSTR_INSERTPROXIES:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  lmn_mem_insert_proxies((LmnMembrane *)wt[targ0], (LmnMembrane *)wt[targ1]);
  break;
}
case INSTR_DELETECONNECTORS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  TR_INSTR_DELETECONNECTORS(targ0, targ1);
  break;
}
case INSTR_REMOVETOPLEVELPROXIES:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  lmn_mem_remove_toplevel_proxies((LmnMembrane *)wt[targ0]);
  break;
}
case INSTR_DEREFFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  TR_INSTR_DEREFFUNC(targ0, targ1, targ2);
  break;
}
case INSTR_LOADFUNC:{
  LmnInstrVar targ0;
  LmnLinkAttr targ1_attr;
  union LmnFunctorLiteral targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL_FUNC(instr, targ1);
  if(LMN_ATTR_IS_DATA(targ1_attr)){
    switch(targ1_attr){
    case LMN_INT_ATTR:
      wt[targ0] = targ1.long_data;
      at[targ0] = LMN_INT_ATTR;
      break;
    case LMN_DBL_ATTR:
      {
  /* 困った */
      }
      break;
    case LMN_STRING_ATTR:
      wt[targ0] = targ1.string_data;
      at[targ0] = LMN_CONST_STR_ATTR;
      break;
    default:
      lmn_fatal("Implementation error");
    }
  }else{
    wt[targ0] = (LmnWord)targ1.functor_data;
    at[targ0] = targ1_attr;
  }
  break;
}
case INSTR_EQFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (at[targ0] != at[targ1]) return FALSE;
  switch (at[targ0]) {
  case LMN_INT_ATTR:
    if ((long)wt[targ0] != (long)wt[targ1]) return FALSE;
    break;
  case LMN_DBL_ATTR:
    if (*(double*)(&wt[targ0]) !=
        *(double*)(&wt[targ1])) return FALSE;
    break;
  default:
    if (wt[targ0] != wt[targ1]) return FALSE;
    break;
  }
 
  break;
}
case INSTR_NEQFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (at[targ0] == at[targ1]) {
    switch (at[targ0]) {
    case LMN_INT_ATTR:
      if ((long)wt[targ0] == (long)wt[targ1]) return FALSE;
      break;
    case LMN_DBL_ATTR:
      if (*(double*)(&wt[targ0]) ==
          *(double*)(&wt[targ1])) return FALSE;
      break;
    default:
      if (wt[targ0] == wt[targ1]) return FALSE;
      break;
    }
  }
  break;
}
case INSTR_ADDATOM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  lmn_mem_push_atom((LmnMembrane *)wt[targ0], wt[targ1], at[targ1]);
  break;
}
case INSTR_MOVECELLS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  lmn_mem_move_cells((LmnMembrane *)wt[targ0], (LmnMembrane *)wt[targ1]);
  break;
}
case INSTR_REMOVETEMPORARYPROXIES:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  lmn_mem_remove_temporary_proxies((LmnMembrane *)wt[targ0]);
  break;
}
case INSTR_NFREELINKS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (!lmn_mem_nfreelinks((LmnMembrane *)wt[targ0], targ1)) return FALSE;
  break;
}
case INSTR_COPYCELLS:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = (LmnWord)lmn_mem_copy_cells((LmnMembrane *)wt[targ1], (LmnMembrane *)wt[targ2]);
  break;
}
case INSTR_LOOKUPLINK:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  TR_INSTR_LOOKUPLINK(targ0, targ1, targ2);
  break;
}
case INSTR_CLEARRULES:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  vec_clear(&((LmnMembrane *)wt[targ0])->rulesets);
  break;
}
case INSTR_DROPMEM:{
  LmnInstrVar targ0;
  READ_VAL(LmnInstrVar, instr, targ0);
  lmn_mem_drop((LmnMembrane *)wt[targ0]);
  break;
}
case INSTR_TESTMEM:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  if (LMN_PROXY_GET_MEM(wt[targ1]) != (LmnMembrane *)wt[targ0]) return FALSE;
  break;
}
case INSTR_IADDFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = wt[targ1] + wt[targ2];
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_ISUBFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = wt[targ1] - wt[targ2];
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IMULFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = wt[targ1] * wt[targ2];
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IDIVFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = wt[targ1] / wt[targ2];
  at[targ0] = LMN_INT_ATTR;
  break;
}
case INSTR_IMODFUNC:{
  LmnInstrVar targ0;
  LmnInstrVar targ1;
  LmnInstrVar targ2;
  READ_VAL(LmnInstrVar, instr, targ0);
  READ_VAL(LmnInstrVar, instr, targ1);
  READ_VAL(LmnInstrVar, instr, targ2);
  wt[targ0] = wt[targ1] % wt[targ2];
  at[targ0] = LMN_INT_ATTR;
  break;
}
    default:
      fprintf(stderr, "interpret_generated: Unknown operation %d\n", op);
      exit(1);
    }
  }
}
