/* Copyright 1989, 1990 by James Aspnes, David Applegate, and Bennet Yee */
/* See the file COPYING for distribution information */
#include "db.h"
#include "bytecode.h"
#include "set.h"
#include "globals.h"
#include "externs.h"
#define BINOP(token, op) case token: sp--; *sp = sp[0] op sp[1]; break;
#define FUNC1(token, f) case token: *sp = f(*sp); break;
#define FUNC2(token, f) case token: sp--; *sp = f(sp[0], sp[1]); break;
#define FUNC3(token, f) \
case token: sp-=2; *sp = f(sp[0], sp[1], sp[2]); break;
#define VALUE(token, v) case token: *++sp = v; break;
#define SLOT(token, s) case token: *sp = safe_get(*sp, s); break;
#define PROC1(token, f) case token: f(*sp--); break;
extern set lookup_setvar (datum, datum);
int run_code (byte * c)
{
datum next;
byte *pc;
datum stack[STACKSIZE];
datum *sp;
int count;
set savelist;
set_iterator next_iterator;
if (c == 0)
return -1;
next = NOTHING;
savelist = empty_set ();
for (sp = stack, pc = c, count = 0; *pc != RETURN_OP; pc++, count++) {
switch (*pc) {
FUNC2 (MOVE_OP, move);
FUNC2 (MATCHES_OP, matches);
FUNC2 (UNSET_OP, unset);
FUNC3 (SET_OP, set_variable);
FUNC3 (SET_STRING_OP, set_string);
FUNC2 (UNSET_ACTION_OP, unset_action);
FUNC3 (SET_ACTION_OP, set_action);
FUNC2 (LOOKUP_OP, lookup);
FUNC2 (LOOKUP_ACTION_OP, lookup_action);
FUNC1 (NOT_OP, !);
VALUE (TRUE_OP, 1);
VALUE (FALSE_OP, 0);
VALUE (ME_OP, me);
VALUE (YOU_OP, you);
VALUE (NEXT_OP, next);
VALUE (TEXT_OP, text);
VALUE (MTEXT_OP, mtext);
SLOT (LOC_OP, location);
VALUE (TELL_OP, do_tell ());
VALUE (CREATE_OP, create ());
FUNC1 (DESTROY_OP, destroy);
PROC1 (TELL_INIT_OP, tell_init);
PROC1 (ADD_BUF_OP, add_buffer);
PROC1 (ADD_NUM_BUF_OP, add_num_buffer);
PROC1 (ADD_TIME_BUF_OP, add_time_buffer);
FUNC1 (SYSCALL_OP, do_syscall);
FUNC1 (NEGATE_OP, -);
FUNC2 (CLEAR_SET_OP, clear_set_var);
FUNC3 (ADD_SET_OP, add_to);
FUNC3 (DEL_SET_OP, take_from);
FUNC2 (COUNT_OP, count_set_var);
FUNC3 (CONTAINS_OP, contains);
VALUE (TIME_OP, time (0));
FUNC1 (DELAY_OP, delay);
FUNC2 (CONCAT_OP, concat);
FUNC1 (NUM_TO_STRING_OP, num_to_string);
/* binary numeric operations */
BINOP (PLUS_OP, +);
BINOP (MINUS_OP, -);
BINOP (TIMES_OP, *);
BINOP (DIV_OP, /);
BINOP (MOD_OP, %);
BINOP (LT_OP, <);
BINOP (GT_OP, >);
BINOP (LEQ_OP, <=);
BINOP (GEQ_OP, >=);
BINOP (EQ_OP, ==);
BINOP (NEQ_OP, !=);
case EXIT_OP:
goto exit;
case JUMP_OP:
pc += ARG_VALUE (pc + 1);
break;
case JUMP_BACK_OP:
pc -= ARG_VALUE (pc + 1);
break;
case JUMP_IF_OP:
if (*sp-- != NOTHING) {
pc += ARG_VALUE (pc + 1);
} else {
pc += ARG_WIDTH;
}
break;
case DO_SET_INIT_OP:
free_set (savelist);
sp -= 2;
savelist = copy_set (lookup_setvar (sp[1], sp[2]));
next = set_first (savelist, &next_iterator);
break;
case MATCHING_DO_SET_INIT_OP:
free_set (savelist);
sp -= 3;
savelist = lookup_setvar (sp[1], sp[2]);
set_build_name_list (savelist); /* build before copy */
savelist = copy_set (savelist);
next = set_first_match (savelist, &next_iterator, sp[3]);
break;
case DO_NEXT_OP:
next = set_next (savelist, &next_iterator);
break;
case MATCHING_DO_NEXT_OP:
next = set_next_match (savelist, &next_iterator);
break;
case LITERAL_OP:
*++sp = ARG_VALUE (pc + 1);
pc += ARG_WIDTH;
break;
case DROP_OP:
sp--;
break;
case DUP_OP:
sp[1] = sp[0];
sp++;
break;
case RANDOM_OP:
*++sp = RAND ();
break;
default:
abort ();
}
}
exit:
return count;
}
int run_action (datum action)
{
const char *s;
datum *code;
char buf[MAX_STRLEN];
if ((code = get_compiled_string (action)) == 0) {
/* try compiling it */
if ((s = string (action)) == 0) {
return -1; /* we lose completely */
} else {
code = compile (s);
if (code == 0) {
sprintf (buf, LOSE_CODE, compile_error);
code = compile (buf);
}
set_compiled_string (action, code);
}
}
return run_code (code);
}