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

#ifndef _COOL_H_
#define _COOL_H_
#include "string.h"

typedef enum	Type_spec {
    STR, NUM, OBJ, LIST, ERR, PC
} Type_spec;

typedef struct Var  Var;

typedef struct	Objid {
    short	server;		/* server id (0 == this server) */
    int		id;		/* object id */
} Objid;

typedef struct	List {
    int		 len;		/* length of value */
    int		 mem;		/* memory actually allocated */
    int		 ref;		/* reference count */
    Var		*el;		/* elements of list or string */
} List;

typedef enum	Error {
    E_NONE, E_TYPE, E_RANGE, E_INVIND, E_DIV, E_MAXREC,
    E_METHODNF, E_VARNF, E_VERBNF, E_FOR, E_PERM, E_SERVERNF, E_SERVERDN,
    E_OBJNF, E_MESSAGE, E_TIMEOUT, E_STACKUND, E_STACKOVR, E_INTERNAL,
    E_FILE, E_ARGTYPE, E_NARGS, E_TICKS, E_TERM
} Error;

#define NERRS 24

/*
 * cannot ignore or catch these errors
 */
#define NOIGNORE(err) (err == E_STACKUND || err == E_STACKOVR \
		    || err == E_INTERNAL || err == E_TICKS)

struct	Var {
    Type_spec	type;
    union {
	int	 num;		/* number */
	Objid	 obj;		/* object id */
	String	*str;		/* string header */
	List	*list;		/* list header */
	Error	 err;		/* error */
    } v;
};

typedef struct HashT {
    int		size;
    int		num;
    void      **table;	/* have to use void *, for multiple datatypes */
} HashT;

typedef struct Symbol {
    int		 ref;	/* local object references to symbol */
    String	*s;	/* symbol */
} Symbol;

#define ISTRUE(x)  ((x.type == NUM && x.v.num) \
		||  (x.type == STR && x.v.str->str[0]) \
		||  (x.type == OBJ && x.v.obj.id >= 0) \
		||  (x.type == LIST && x.v.list->len))

typedef int	Inst;
typedef struct Method	Method;
typedef struct Verbdef		Verbdef;
typedef struct Vardef		Vardef;

typedef struct Lock		Lock;

struct Lock {
    String	*name;
    int		 added_by;	/* msgid which added this lock */
    Lock	*next;
};

typedef struct Object {
    Objid	 id;		/* object's id */
    int		 ref;		/* reference count */
    List	*parents;	/* parent list */
    Lock	*locks;
    HashT	*methods;	/* method list, hashed */
    Verbdef	*verbs;
    HashT	*vars;		/* variables, hashed */
    int		 var_hashsize;
    int		 nsymb;		/* number of symbols */
    int		 st_size;	/* memory actually allocated for symbols */
    Symbol	*symbols;	/* symbol table */
    int		 last_search;	/* generational flag, last search on object */
				/* kudos to greg hudson for the idea */
} Object;

enum eh { EH_DEFAULT, EH_IGNORE, EH_CATCH };

struct Method {
    int		 name;			/* index into symbol table */
    int		 ninst;			/* number of instructions in machine */
    Inst	*code;			/* the compiled code */
    enum eh	 ehandler[NERRS];	/* error handler */
    Vardef	*vars;			/* local variables */
    int		 ref;			/* reference count */
    Method	*next;			/* next method in linked list */
    int		 blocked : 1;		/* non-overrideable ("nomask") flag  */
};

struct Verbdef {
    int		 verb;			/* name of verb */
    int		 prep;			/* preposition, or -1 for none */
    int		 method;		/* method to call */
    Verbdef	*next;			/* next verbdef in linked list */
};

struct Vardef {
    int		 name;			/* index into symbol table */
    Var		 value;			/* value */
    Vardef	*next;			/* next vardef in linked list */
};

enum state	{ RUNNING,	/* program is running */
		   STOPPED,	/* program stopped by return or end of code */
		   HALTED,	/* program halted by method called */
		   RAISED,	/* program stopped by raise() */
		   BLOCKED };	/* program blocked on event */

typedef void (*PFV)(void);

typedef enum Sys_sym {
    BLANK, INIT, PARSE, BOOT_SERVER, CONNECT_SERVER, DISCONNECT_SERVER,
    CONNECT_PLAYER, CREATE_PLAYER, DISCONNECT_PLAYER, NAME,
    PASSWORD, RAISE, RETURN
} Sys_sym;

enum arg_type { none, NUM_ARG, ID_ARG, STR_ARG, VARNO_ARG };

typedef struct Op_entry {
    int		opcode;
    const char  name[MAX_TOKEN_LEN];
    PFV		func;
    int		nargs;
    enum arg_type	arg_type[3];
} Op_entry;

#endif /* !_COOL_H_ */