;  This file is part of cqual.
;  Copyright (C) 2000-2001 The Regents of the University of California.
;
; cqual is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; cqual is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with cqual; see the file COPYING.  If not, write to
; the Free Software Foundation, 59 Temple Place - Suite 330,
; Boston, MA 02111-1307, USA.

(defmacro defset (name set-info-var element-type)
  `(defset* ',name ',set-info-var ',element-type))

(setq sets nil)

(defun defset* (name set-info-var element-type)
  (if (assoc name sets)
      (message (format "Set %s already declared" name))
    (setq sets (cons (list name set-info-var element-type) sets))))

(defun build-file (file-name)
  (let ((buffer (create-file-buffer file-name))
	(debug-on-error (or debug-on-error
			    (interactive-p))))
    (if debug-on-error
	(switch-to-buffer buffer)
      (set-buffer buffer))
    (fill-buffer)
    (write-file file-name)
    (unless debug-on-error
      (kill-buffer buffer))))

(defun copyright-notice ()
  (insert "/* Automatically generated file, do not edit. See containters.def */\n\n")
  (insert "/* Copyright (c) 2000-200 The Regents of the University of California. */\n")
  (insert "/* See the copyright notice in nodetypes.def for distribution restrictions */\n"))

(defun write-intro ()
  (copyright-notice)
  (insert "#ifndef CONTAINERS_H\n"
	  "#define CONTAINERS_H\n"
	  "#include \"set.h\"\n"
	  "#include \"AST.h\"\n"))

(defun write-epilogue ()
  (insert "#endif\n"))

(defun fill-set (name set-info-var element-type)
  (insert (format "extern struct Set_info %s;\n" set-info-var)
	  (format "typedef struct { set s; } %s;\n" name)
	  (format "typedef struct { set_scanner ss; } %s_scanner;\n" name)
	  (format "static inline %s to_%s(set s) { %s new_s = { s }; return new_s; }\n" name name name)
	  (format "static inline %s empty_%s(void) { return to_%s(empty_set); }\n" name name name)
	  (format "static inline %s %s_copy(region r, %s s) { return to_%s(set_copy(r, s.s)); }\n" name name name name)
	  (format "static inline bool %s_empty(%s s) { return set_empty(s.s); }\n" name name)
	  (format "static inline bool %s_member(%s s, %s elt) { return set_member(&%s, s.s, (void *) elt); }\n" name name element-type set-info-var)
	  (format "static inline int %s_size(%s s) { return set_size(s.s); }\n" name name)
	  (format "static inline void %s_insert(region r, %s *s, %s elt) { set_insert(r, &%s, &s->s, (void *) elt); }\n" name name element-type set-info-var)
	  (format "static inline void %s_remove(%s *s, %s elt) { set_remove(&%s, &s->s, (void *) elt); }\n" name name element-type set-info-var)
	  (format "static inline bool %s_subset(%s s1, %s s2) { return set_subset(&%s, s1.s, s2.s); }\n" name name name set-info-var)
	  (format "static inline %s %s_union(%s s1, %s s2) { return to_%s(set_union(&%s, s1.s, s2.s)); }\n" name name name name name set-info-var)
	  (format "static inline bool %s_single(%s s) { return set_single(s.s); }\n" name name)
	  (format "static inline void %s_sort(%s s) { set_sort(&%s, s.s); }\n" name name set-info-var)
	  (format "static inline void %s_scan(%s s, %s_scanner *ss) { set_scan(s.s, &ss->ss); }\n" name name name)
	  (format "static inline %s %s_next(%s_scanner *ss) { return (%s) set_next(&ss->ss); }\n" element-type name name element-type)
	  (format "#define scan_%s(var, scanner, set) for (%s_scan(set, &scanner), var = %s_next(&scanner); var; var = %s_next(&scanner))\n\n" name name name name)
))

(defun fill-buffer ()
  (write-intro)
  (mapcar (lambda (args) (apply #'fill-set args)) sets)
  (write-epilogue)
)

(load-file "containers.def")
(build-file "containers.h")
