/******************************************************************************
 *
 * 9998sketch/symbol.h
 *
 * (c) Eugene K. Ressler, Jr. 2004, 2005
 *
 * A program related to the book
 *
 * Fundamentals of Virtual World Simulation
 * by Eugene K. Ressler, Jr.
 *
 * No warranty of correctness or capability of any kind is expressed or implied.
 *
 * The author grants free use of this code for any purpose as long any text,
 * executable program, library file, or source code distributed to others 
 * and employing any portion of this code clearly cites the book named above.
 *
 ******************************************************************************/

#ifndef __SYMBOL_H
#define __SYMBOL_H

#include "error.h"
#include "scene.h"

typedef char SYMBOL_NAME[32];

typedef struct symbol_t {
  struct symbol_t *next;
  SYMBOL_NAME name, tag;
  SRC_LINE def_line;
  int n_references;
  OBJECT *obj;
} SYMBOL;

#define SYMBOL_HASH_SIZE  79

typedef struct symbol_table_t {
  struct symbol_table_t *enclosing;
  SYMBOL *head[SYMBOL_HASH_SIZE];
} SYMBOL_TABLE;

// chain a new scope onto an existing symbol table (or NULL)
// and return the new table
SYMBOL_TABLE *new_scope(SYMBOL_TABLE *sym_tab);

// unchain the inner scope from an existing symbol table
// and return the next outer scope or NULL if this was
// the outermost scope
SYMBOL_TABLE *old_scope(SYMBOL_TABLE *sym_tab);

// look up a symbol of the given name in all the scopes of the
// provided symbol table
SYMBOL *lookup(SYMBOL_TABLE *sym_tab, char *name);

// look up a symbol with type checking and value extraction
void look_up_tag(SYMBOL_TABLE *sym_tab, int *exists_p, SRC_LINE line, char *name);
void look_up_opts(SYMBOL_TABLE *sym_tab, OPTS **opts, SRC_LINE line, char *name);
void look_up_scalar(SYMBOL_TABLE *sym_tab, FLOAT *r, SRC_LINE line, char *name);
void look_up_point(SYMBOL_TABLE *sym_tab, POINT_3D r, SRC_LINE line, char *name);
void look_up_vector(SYMBOL_TABLE *sym_tab, VECTOR_3D r, SRC_LINE line, char *name);
void look_up_transform(SYMBOL_TABLE *sym_tab, TRANSFORM r, SRC_LINE line, char *name);
void look_up_drawable(SYMBOL_TABLE *sym_tab, OBJECT **r, SRC_LINE line, char *name);

// predicated for tag existence; raises error if not
int tag_exists_p(SYMBOL_TABLE *sym_tab, char *name);

// insert a given name in the symbol table
SYMBOL *new_symbol(SYMBOL_TABLE *sym_tab, char *name, char *tag, OBJECT *obj, SRC_LINE def_line);
OBJECT *remove_symbol(SYMBOL_TABLE *sym_tab, char *name, SRC_LINE line);

#endif
