/* Copyright (c) 1993 Stephen F. White */

#include "cool.h"
#include "proto.h"
#include "execute.h"
#include "y.tab.h"

Op_entry opcode_info[] = {
  {IF, "IF", op_if, 2, {NUM_ARG, NUM_ARG}},
  {ELSEIF, "ELSEIF", op_elseif, 1, {NUM_ARG}},
  {ELSE, "ELSE", op_null, 0, {0}},
  {FOR, "FOR", op_for, 2, {VARNO_ARG, NUM_ARG}},
  {FORRNG, "FORRNG", op_forrng, 2, {VARNO_ARG, NUM_ARG}},
  {WHILE, "WHILE", op_while, 1, {NUM_ARG}},
  {DO, "DO", op_do, 1, {NUM_ARG}},
  {DOWHILE, "DOWHILE", op_dowhile, 2, {NUM_ARG, NUM_ARG}},
  {AT, "AT", op_at, 1, {NUM_ARG}},
  {PUSHPC, "PUSHPC", op_pushpc, 0, {0}},
  {SLEEP, "SLEEP", op_sleep, 1, {NUM_ARG}},
  {NUMPUSH, "NUMPUSH", op_numpush, 1, {NUM_ARG}},
  {STRPUSH, "STRPUSH", op_strpush, 1, {STR_ARG}},
  {OBJPUSH, "OBJPUSH", op_objpush, 2, {NUM_ARG, NUM_ARG}},
  {LISTPUSH, "LISTPUSH", op_listpush, 1, {NUM_ARG}},
  {MAPPUSH, "MAPPUSH", op_mappush, 1, {NUM_ARG}},
  {ERRPUSH, "ERRPUSH", op_errpush, 1, {NUM_ARG}},
  {GETLVAR, "GETLVAR", op_getlvar, 1, {VARNO_ARG}},
  {GETGVAR, "GETGVAR", op_getgvar, 1, {ID_ARG}},
  {GETGVAREXPR, "GETGVAREXPR", op_getgvarexpr, 1, {NUM_ARG}},
  {ASGNLVAR, "ASGNLVAR", op_asgnlvar, 1, {VARNO_ARG}},
  {ASGNGVAR, "ASGNGVAR", op_asgngvar, 1, {ID_ARG}},
  {ASGNGVAREXPR, "ASGNGVAREXPR", op_asgngvarexpr, 1, {NUM_ARG}},
  {ASGNLVARINDEX, "ASGNLVARINDEX", op_asgnlvarindex, 1, {VARNO_ARG}},
  {ASGNGVARINDEX, "ASGNGVARINDEX", op_asgngvarindex, 1, {ID_ARG}},
  {PARENTS, "PARENTS", op_parents, 0, {0}},
  {THIS, "THIS", op_this, 0, {0}},
  {PLAYER, "PLAYER", op_player, 0, {0}},
  {CALLER, "CALLER", op_caller, 0, {0}},
  {ARGS, "ARGS", op_args, 0, {0}},
  {SETPLAYER, "SETPLAYER", op_setplayer, 0, {0}},
  {ADD, "ADD", op_add, 0, {0}},
  {SUB, "SUB", op_sub, 0, {0}},
  {MUL, "MUL", op_mul, 0, {0}},
  {DIV, "DIV", op_div, 0, {0}},
  {MOD, "MOD", op_mod, 0, {0}},
  {NEGATE, "NEGATE", op_negate, 0, {0}},
  {AND, "AND", op_and, 1, {NUM_ARG}},
  {OR, "OR", op_or, 1, {NUM_ARG}},
  {ENDAND, "ENDAND", op_null, 0, {0}},
  {ENDOR, "ENDOR", op_null, 0, {0}},
  {NOT, "NOT", op_not, 0, {0}},
  {EQ, "EQ", op_eq, 0, {0}},
  {NE, "NE", op_ne, 0, {0}},
  {GT, "GT", op_gt, 0, {0}},
  {GE, "GE", op_ge, 0, {0}},
  {LT, "LT", op_lt, 0, {0}},
  {LE, "LE", op_le, 0, {0}},
  {MESSAGE, "MESSAGE", op_message, 2, {NUM_ARG, STR_ARG}},
  {MESSAGE_EXPR, "MESSAGE_EXPR", op_message_expr, 1, {NUM_ARG}},
  {INDEX, "INDEX", op_index, 0, {0}},
  {IN, "IN", op_in, 0, {0}},
  {SUBSET, "SUBSET", op_subset, 0, {0}},
  {LSUBSET, "LSUBSET", op_lsubset, 0, {0}},
  {RSUBSET, "RSUBSET", op_rsubset, 0, {0}},
  {LENGTHOF, "LENGTHOF", op_lengthof, 1, {NUM_ARG}},
  {SETADD, "SETADD", op_setadd, 1, {NUM_ARG}},
  {SETREMOVE, "SETREMOVE", op_setremove, 1, {NUM_ARG}},
  {LISTINSERT, "LISTINSERT", op_listinsert, 1, {NUM_ARG}},
  {LISTAPPEND, "LISTAPPEND", op_listappend, 1, {NUM_ARG}},
  {LISTDELETE, "LISTDELETE", op_listdelete, 1, {NUM_ARG}},
  {LISTASSIGN, "LISTASSIGN", op_listassign, 1, {NUM_ARG}},
  {EXPLODE, "EXPLODE", op_explode, 1, {NUM_ARG}},
  {STRSUB, "STRSUB", op_strsub, 1, {NUM_ARG}},
  {PAD, "PAD", op_pad, 1, {NUM_ARG}},
  {PSUB, "PSUB", op_psub, 1, {NUM_ARG}},
  {RANDOM, "RANDOM", op_random, 1, {NUM_ARG}},
  {TOSTR, "TOSTR", op_tostr, 1, {NUM_ARG}},
  {TONUM, "TONUM", op_tonum, 1, {NUM_ARG}},
  {TOOBJ, "TOOBJ", op_toobj, 1, {NUM_ARG}},
  {TOERR, "TOERR", op_toerr, 1, {NUM_ARG}},
  {TYPEOF, "TYPEOF", op_typeof, 1, {NUM_ARG}},
  {SERVEROF, "SERVEROF", op_serverof, 1, {NUM_ARG}},
  {SERVERNAME, "SERVERNAME", op_servername, 1, {NUM_ARG}},
  {SERVERS, "SERVERS", op_servers, 1, {NUM_ARG}},
  {STOP, "STOP", op_stop, 0, {0}},
  {T_RAISE, "RAISE", op_raise, 0, {0}},
  {T_RETURN, "RETURN", op_return, 0, {0}},
  {BREAK, "BREAK", op_break, 1, {NUM_ARG}},
  {CONTINUE, "CONTINUE", op_continue, 1, {NUM_ARG}},
  {ECHO, "ECHO", op_echo, 1, {NUM_ARG}},
  {ECHO_FILE, "ECHO_FILE", op_echo_file, 1, {NUM_ARG}},
  {TIME, "TIME", op_time, 1, {NUM_ARG}},
  {CTIME, "CTIME", op_ctime, 1, {NUM_ARG}},
  {CLONE, "CLONE", op_clone, 1, {NUM_ARG}},
  {DESTROY, "DESTROY", op_destroy, 1, {NUM_ARG}},
  {CHPARENTS, "CHPARENTS", op_chparents, 1, {NUM_ARG}},
  {FIND_METHOD, "FIND_METHOD", op_find_method, 1, {NUM_ARG}},
  {SPEW_METHOD, "SPEW_METHOD", op_spew_method, 1, {NUM_ARG}},
  {LIST_METHOD, "LIST_METHOD", op_list_method, 1, {NUM_ARG}},
  {DECOMPILE, "DECOMPILE", op_decompile, 1, {NUM_ARG}},
  {POP, "POP", op_pop, 0, {0}},
  {CRYPT, "CRYPT", op_crypt, 1, {NUM_ARG}},
  {CHECKMEM, "CHECKMEM", op_checkmem, 1, {NUM_ARG}},
  {CACHE_STATS, "CACHE_STATS", op_cache_stats, 1, {NUM_ARG}},
  {LOCK, "LOCK", op_lock, 1, {NUM_ARG}},
  {UNLOCK, "UNLOCK", op_unlock, 1, {NUM_ARG}},
  {HASPARENT, "HASPARENT", op_hasparent, 1, {NUM_ARG}},
  {OBJSIZE, "OBJSIZE", op_objsize, 1, {NUM_ARG}},
  {VARS, "VARS", op_vars, 1, {NUM_ARG}},
  {VERBS, "VERBS", op_verbs, 1, {NUM_ARG}},
  {METHODS, "METHODS", op_methods, 1, {NUM_ARG}},
  {VERB, "VERB", op_verb, 1, {NUM_ARG}},
  {RMVERB, "RMVERB", op_rmverb, 1, {NUM_ARG}},
  {RMMETHOD, "RMMETHOD", op_rmmethod, 1, {NUM_ARG}},
  {RMVAR, "RMVAR", op_rmvar, 1, {NUM_ARG}},
  {PROGRAM, "PROGRAM", op_program, 1, {NUM_ARG}},
  {COMPILE, "COMPILE", op_compile, 1, {NUM_ARG}},
  {MATCH, "MATCH", op_match, 1, {NUM_ARG}},
  {MATCH_FULL, "MATCH_FULL", op_match_full, 1, {NUM_ARG}},
  {SHUTDOWN, "SHUTDOWN", op_shutdown, 1, {NUM_ARG}},
  {DUMP, "DUMP", op_dump, 1, {NUM_ARG}},
  {WRITELOG, "WRITELOG", op_writelog, 1, {NUM_ARG}},
  {QUIT, "QUIT", op_boot, 1, {NUM_ARG}},
  {KILL, "KILL", op_kill, 1, {NUM_ARG}},
  {PS, "PS", op_ps, 1, {NUM_ARG}},
  {PASS, "PASS", op_pass, 2, {NUM_ARG, NUM_ARG}},
};

Op_entry *opcodes[LAST_TOKEN];

void opcode_init (void)
{
  int i;

  for (i = 0; i < LAST_TOKEN; i++) {
    opcodes[i] = 0;
  }
  for (i = 0; i < Arraysize (opcode_info); i++) {
    opcodes[opcode_info[i].opcode] = &opcode_info[i];
  }
}

void opcode_free_symbols (Object * o, Method * m)
{
  int pc = 0, arg;
  Op_entry *entry;

  while (pc < m->ninst) {
    if (!(entry = opcodes[m->code[pc++]])) {
      return;
    }
    for (arg = 0; arg < entry->nargs; arg++, pc++) {
      if (entry->arg_type[arg] == STR_ARG || entry->arg_type[arg] == ID_ARG) {
        sym_free (o, m->code[pc]);
      }
    }
  }
}