#ifndef __GSK_LISP_NAMESPACE_H_
#define __GSK_LISP_NAMESPACE_H_

typedef struct _GskLispNamespace GskLispNamespace;
typedef struct _GskLispMarshal GskLispMarshal;
typedef struct _GskLispCodec GskLispCodec;

typedef void (*GskLispFunc) ();
#define GSK_LISP_FUNC(func)		((GskLispFunc)(func))


#include "gsklispnode.h"
#include "gsklispinput.h"
#include "../gskgtk.h"

typedef gpointer (*GskLispCompiler) (gpointer          compiler_data,
				     GtkType           type,
				     GskLispNode      *node,
				     GskLispNamespace *ns,
				     gpointer          marshal_data,
				     char            **err_msg);
typedef gboolean (*GskLispRunner)   (GskLispFunc       func,
				     gpointer          func_data,
				     GtkArg           *result,
				     GskLispNamespace *ns,
				     gpointer          compiled_data,
				     gpointer          marshal_data,
				     char            **err_msg);

struct _GskLispMarshal
{
  GskLispCompiler compiler;
  GskLispRunner runner;
  GDestroyNotify compiled_data_destroy;
  gpointer marshal_data;
  GDestroyNotify marshal_data_destroy;
};


GskLispNamespace *gsk_lisp_namespace_new       ();
void              gsk_lisp_namespace_ref       (GskLispNamespace *ns);
void              gsk_lisp_namespace_unref     (GskLispNamespace *ns);

/* adding sub-namespaces */
void              gsk_lisp_namespace_add_sub   (GskLispNamespace *ns,
						const char       *name,
						GskLispNamespace *subns);

/* set a variable in to the namespace */
void              gsk_lisp_namespace_add_value (GskLispNamespace *ns,
						GtkArg           *arg);

/* look up a variable's value in the namespace */
gboolean          gsk_lisp_namespace_lookup_val(GskLispNamespace *ns,
						guint             num_names,
						const char       *names[],
						GtkArg           *result);


/* --- defining new functions --- */
void              gsk_lisp_namespace_add_func  (GskLispNamespace *ns,
						const char       *name,
						GskLispFunc       func,
						GskLispMarshal   *marshal,
						gpointer          compiler_data,
						GDestroyNotify    compiler_data_destroy,
						gpointer          func_data,
						GDestroyNotify    destroy);
void              gsk_lisp_namespace_add_func_c(GskLispNamespace *ns,
						const char       *name,
						GskLispFunc       func,
						GskLispMarshal   *marshal);
#if 0
/* --- allocating new private types (not implemented) --- */
GskLispType  gsk_lisp_namespace_new_array_type (GskLispNamespace *context,
					        GskLispType       sub_type,
					        const char       *type_name);
GskLispType  gsk_lisp_namespace_new_struct_type(GskLispNamespace *context,
					        guint             num_elements,
					        const GskLispType*elements,
					        const char       *type_name);
#endif

struct _GskLispCodec
{
  /*< private >*/
  GskLispRunner     runner;
  gpointer          compiled_data;
  GDestroyNotify    compiled_data_destroy;
  GskLispFunc       func;
  gpointer          func_data;
  GtkType           return_type;
  gpointer          marshal_data;
};

GskLispCodec     *gsk_lisp_namespace_compile   (GskLispNamespace *ns,
						GskLispNode      *node,
						GtkType           type,
						char            **err_msg);
gboolean          gsk_lisp_codec_is_runnable   (GskLispCodec     *codec);
gboolean          gsk_lisp_codec_run           (GskLispCodec     *codec,
		                                GtkArg           *result,
		                                GskLispNamespace *ns,
						char            **err_msg);
void              gsk_lisp_codec_destroy       (GskLispCodec     *codec);

void              gsk_lisp_namespace_nick      (GskLispNamespace *ns,
						const char       *nickname,
						GtkType           type);
const char       *gsk_lisp_namespace_get_nick  (GskLispNamespace *ns,
						GtkType           type);

/* --- implementation helpers --- */
void gsk_lisp_prefix_err_msg (char **msg, const char *fmt, ...);

/* --- debugging --- */
#ifdef GSK_DEBUG
GskLispCodec     *gsk_lisp_namespace_compile_debug(GskLispNamespace *ns,
						   GskLispNode      *node,
						   GtkType           type,
						   char            **err_msg,
						   const char       *file,
						   int               line);
#define gsk_lisp_namespace_compile(ns,node,type,err_msg)		\
	gsk_lisp_namespace_compile_debug(ns,node,type,err_msg,__FILE__,__LINE__)
#endif
 
#endif
