;;; -*- mode:lisp;package:user;base:10.;fonts:(cptfontb) -*- 
;;; $Header: /ct/interp/dynsem.l,v 1.177 84/10/30 19:13:50 penny Exp $
;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                              DYNSEM                              ;;;
;;; Mark L. Miller and Paul Robertson               February 8, 1983 ;;;
;;;                                                                  ;;;
;;; This file defines the Dynamic Semantics for Ada, in terms of a   ;;;
;;; function associated with each type of Diana node.  These should  ;;;
;;; always be defined using the definition macros in ds_macs.        ;;;
;;;                                                                  ;;;
;;; NB:  Currently, only a fraction of the 167. node types have been ;;;
;;; implemented.  ++                                                 ;;;
;;;                                                                  ;;;
;;; This file is part of a proprietary software project.  Source     ;;;
;;; code and documentation describing implementation details are     ;;;
;;; available on a confidential, non-disclosure basis only.  These   ;;;
;;; materials, including this file in particular, are trade secrets  ;;;
;;; of Computer * Thought Corporation.                               ;;;
;;;                                                                  ;;;
;;; (c) Copyright 1982 and 1983,  Computer * Thought Corporation.    ;;;
;;;     All Rights Reserved.                                         ;;;
;;;                                                                  ;;;
;;; Reference materials:                                             ;;;
;;;   Foderaro and Sklower, The FRANZ LISP Manual, September 1981.   ;;;
;;;   Weinreb and Moon, LISP MACHINE MANUAL, Symbolics, July 1981.   ;;;
;;;   Charniak et al., 1980.  Artificial Intelligence Programming.   ;;;
;;;   Miller, 1982.  The C*T Ada Tutor: Guide to the Implementation. ;;;
;;;   Tartan Labs, 1982.  The Diana Reference Manual.                ;;;
;;;      ==> Should merge on-line Diana manual with this file! ++    ;;;
;;; The following code assumes familiarity with these materials.     ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Ensure presence of needed files. 

(comment Assumes ct_load and some suitable ct_daba are present)

(eval-when (compile load eval) (ct_load 'stateval))

(eval-when (compile load eval) (ct_load 'aip))	  ;AIP macros pkg. 

(eval-when (compile load eval) (ct_load 'compat)) ;Franz/LM compat pkg. 

(eval-when (compile load eval) (ct_load 'charmac)) ;get #$% and #$~

(eval-when (compile load eval) (ct_load 'time))	  ;Timing functions. 

(eval-when (compile load eval) (ct_load 'diana))  ;LISP rep of datatype.

(eval-when (compile load eval) (ct_load 'ctflav));Flavor compatability.

(eval-when (compile load eval) (ct_load 'dsmacs));Macros.

(eval-when (compile load eval) (ct_load 'adabe))

(eval-when (compile load eval) (ct_load 'ferec))

(eval-when (compile load eval) (ct_load 'attribute))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Compiler Declarations and Global Variables -- 

#+franz (declare (macros t))
(declare (ct_includef 'intrpdcl))
							;Ports/Streams:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Definitions of Diana Nodetypes --


		;;;;;;;;;;;;;;
(def_diana_node dn_compilation(starting referencep types record nuar 
                               mp dead_p cxs cxl)
		;;;;;;;;;;;;;;
;;;types is used to collect the subtype cxonstraints for types
;;;and the formals for parameters respectively. Each is an A-List indexed
;;;by the defining (dn...id ...) node.
;;;starting is t as long as the program is searching for the main procedure.

      (ds_if #$~dead_p
	     (ds_exit))
      (%= #$~starting t)		; we are looking for the main procedure.
      (%= *exchandler* nil)
      (ds_if *package_standard*
	     (ct_send *activation* 'set-locals *package_standard*)
	     (ds_call_diana (ada_declared (ada_ident standard) nil 'package)));with standard;
      (%= *package_standard* (ct_send *activation* 'locals))
      (%= #$~mp (ds_find_main_prog pc))
      (%= #$~cxs (ds_find_list_of_contexts #$%as_list #$~mp))
      (ds_label #$~cxl)
      (ds_if (and #$~cxs
		  (diana_nodep (car #$~cxs))
		  (eq (diana_nodetype_get (car #$~cxs))
		      'dn_package_id))
	     (ds_call_diana (ds_pop #$~cxs))
	     (ds_pop #$~cxs))
      (ds_if #$~cxs (ds_goto #$~cxl))
      ;(break look-at-cntxt)
  ;;; execute the main program.
  (let ((ar (make_activation_record 1 0))
	(asbdydes (diana_get
		    (diana_get #$~mp 'as_unit_body)
		    'as_designator)))
    (set-iv adabe_activation ar 'locals nil)
    (set-iv adabe_activation ar 'pc asbdydes)
					  ; start procedure at the start.
    (set-iv adabe_activation ar 'node asbdydes)
    (%= #$~nuar ar)			  ; make an empty AR.
    (%= *nuactivation* ar))		  ; driver will switch in nuactivation 
					  ; record on the next cycle of
					  ; the virtual machine.
  (ds_break)				  ; stage

  (ct_send *current_task* 'make_wait_for_inferiors
	   (ct_send *current_task* 'inferior_tasks))
  (%= #$~dead_p t)			  ;time to go die.
  (ds_follow pc)			  ;by the time I get there I'll be dead.
)


		;;;;;;;;;;;;
(def_diana_node dn_comp_unit()
                ;;;;;;;;;;;;
   (cond (#$%as_context (ds_call_diana #$%as_context))))

#|;  (break look-at-as-unit-body)
  ;;; elaborate the context
  (ds_if #$~dead_p
	 (progn
	   (ct_send *current_task* 'kill_yourself_and_inferiors)
	   (ds_exit))
	 (cond (#$%as_context (ds_call_diana #$%as_context))));stage

  ;;; execute the body
  (let ((ar (make_activation_record 1 0))
	(asbdydes (diana_get #$%as_unit_body 'as_designator)))
    (set-iv adabe_activation ar 'locals nil)
    (set-iv adabe_activation ar 'pc asbdydes)
					  ; start procedure at the start.
    (set-iv adabe_activation ar 'node asbdydes)
    (%= #$~nuar ar)			  ; make an empty AR.
    (%= *nuactivation* ar))		  ; driver will switch in nuactivation 
					  ; record on the next cycle of
					  ; the virtual machine.
  (ds_break)				  ; stage

  (ct_send *current_task* 'make_wait_for_inferiors
	   (ct_send *current_task* 'inferior_tasks))
  (%= #$~dead_p t)			  ;time to go die.
  (ds_follow pc)			  ;by the time I get there I'll be dead.
)|#

		;;;;;;;;;;
(def_diana_node dn_context (cxl cxs)
		;;;;;;;;;;

  (%= #$~cxs #$%as_list)
  (ds_label #$~cxl)
  (ds_if #$~cxs 
         (ds_call_diana (ds_pop #$~cxs)))
  (ds_if #$~cxs (ds_goto #$~cxl)))

		;;;;;;;
(def_diana_node dn_with (lus lul)
                ;;;;;;;
  (%= #$~lus #$%as_list)
  (ds_label #$~lul)			  ;stage
  
  (let ((flus (first #$~lus)))
    (ds_if (eq (diana_nodetype_get (diana_get flus 'sm_defn))
	       'dn_package_id)
	   (ds_call_diana (diana_get flus 'sm_defn))))
  (ds_break)				  ;stage
  
  (ds_pop  #$~lus )
  (ds_if #$~lus (ds_goto #$~lul))
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Packages


		;;;;;;;;;;;;;
(def_diana_node dn_package_id (genpars genparl)
		;;;;;;;;;;;;;
;   (break in-package-id)
  ; check to see if this is an instantiation and if it is get its
  ; generic parameters and elaborate them
  (%= #$~genpars
      (let* ((ctth (diana_get pc 'ct_threadp))
	     (pkgdecl (car (mapcan #'(lambda(ct)
				       (cond ((and (diana_nodep ct)
						   (eq (diana_nodetype_get ct)
						  'dn_package_decl))
					      (list ct))))
				   ctth)))
	     (pkgdef (and pkgdecl 
		      (diana_get pkgdecl 'as_package_def))))
	(and pkgdef (eq (diana_nodetype_get pkgdef) 'dn_instantiation)
	     (diana_get pkgdef 'sm_decl_s))))
  (ds_label #$~genparl)
  (ds_if #$~genpars
	 (ds_call_diana (ds_pop #$~genpars)))	  ;elaborate the genpars
  (ds_if #$~genpars
	 (ds_goto #$~genparl))

;  (ds_call_diana #$%sm_spec)
  (ds_if (or (and #$%sm_spec 
		  (eq (diana_nodetype_get #$%sm_spec) 'dn_instantiation))
	     #|(and #$%sm_body
		  (memq (diana_nodetype_get #$%sm_body) '(dn_void dn_stub nil)))|#
	     )
	 (ds_exit)
	 (ds_call_diana #$%sm_spec))
  (ds_if (or (and #$%sm_spec 
		  (eq (diana_nodetype_get #$%sm_spec) 'dn_instantiation))
	     (and #$%sm_body
		  (memq (diana_nodetype_get #$%sm_body) '(dn_void dn_stub nil))))
	 (ds_exit)
	 #|(cond
	   ((eq (diana_nodetype_get #$%sm_spec) 'dn_instantiation)
	    (ds_call_diana #$%sm_spec)))|#
	 (ds_call_diana #$%sm_body)))


		;;;;;;;;;;;;;;;
(def_diana_node dn_package_decl()
		;;;;;;;;;;;;;;;
  (ds_if (eq (diana_nodetype_get #$%as_package_def) 'dn_instantiation)
#|	 (ds_call_diana (diana_get
			  (diana_get #$%as_package_def 'as_name)
			  'sm_body))|#
	 (ds_call_diana #$%as_id)
	 (ds_call_diana #$%as_package_def)))

		;;;;;;;;;;;;;;;
(def_diana_node dn_package_body(starting) ;make sure that this isnt selected
		;;;;;;;;;;;;;;;
;  (break frobe)
  (ds_if (not
	   (eq (let*
		 ((smspec (diana_get #$%as_id 'sm_spec))
		  (res (and smspec
			    (diana_nodetype_get
			      (car (diana_get smspec 'ct_threadp))))))
		 res)
	       'dn_generic_id))
	 (let ((abs #$%as_block_stub));(break look-at-me)
	   (ds_if abs
		  (ds_call_diana abs))))) ;elaborate declarations and
    (ds_break)
;  (break in-package-body)		;as ther main program.
;  
					  ;do initialization.
		;;;;;;;;;;;;;;;
(def_diana_node dn_package_spec(types)
		;;;;;;;;;;;;;;;
  (ds_call_diana #$%as_decl_s1)
  (ds_call_diana #$%as_decl_s2))

		;;;;;;;;;
(def_diana_node dn_decl_s(dcls dl record );;possibly others missing?+++
		;;;;;;;;;
  (%= #$~dcls  #$%as_list)
  (ds_label #$~dl)			  ;stage

  (ds_if #$~dcls (ds_call_diana (ds_pop #$~dcls)));stage
  (ds_if #$~dcls (ds_goto #$~dl)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; types and subtypes

       ;;;;;;;;;
(defun type_depth (defocc)
       ;;;;;;;;;
  (- (get-iv adabe_activation *activation* 'pnl)
     (diana_get defocc 'ct_pnl)))
      


		;;;;;;;
(def_diana_node dn_type (res evaluatep invar dscrmt_vars dscrmt_constraints )
		;;;;;;;
 (let ((ats (ds_find_base_type_spec #$%as_type_spec)))
  (%= #$~evaluatep t)
  (cond ((is_dscrmt_record ats)
		    (%= #$~dscrmt_constraints (dscrmt_record%dscrmt ats))
		    (%= #$~dscrmt_vars (dscrmt_record%vars ats))
		    (%= ats (dscrmt_record%record *_*))))
   (ds_if (and ats
	      (not (memq (diana_nodetype_get ats) '(dn_record dn_array))))
	 (ds_call_diana ats)))
 (ds_break)
    (let ((nutype (ct_make_instance 'dt_type_type)))
    ;(break look-for-digits)
    (ct_send nutype 'initialize `(, #$%as_id
				  ,#$~res
				  nil
				  , #$%as_id))
    (let ((*activation*
	    (follow_alink_n_times
	      *activation*
	      (type_depth #$%as_id))))
      (set-iv adabe_activation *activation* 'locals
	      (cons
		(cons  #$%as_id nutype) 
		(get-iv adabe_activation *activation* 'locals) ;the locals slot.
		))))
  (ds_push (cons #$%as_id (first #$~res)) #$^types))


		;;;;;;;;;;
(def_diana_node dn_subtype (res evaluatep invar dscrmt_vars dscrmt_constraints )
		;;;;;;;;;;
  (%= #$~evaluatep t)
  (let ((ds (ds_find_base_type_spec #$%as_constrained)))
    (cond ((is_dscrmt_record ds)
		    (%= #$~dscrmt_constraints (dscrmt_record%dscrmt ds))
		    (%= #$~dscrmt_vars (dscrmt_record%vars ds))
		    (%= ds (dscrmt_record%record *_*))))
    (ds_if (not (is_dscrmt_record ds))
	   (ds_call_diana ds)))
  (ds_break)
    (let* ((nutype (ct_make_instance 'dt_type_type))
	   (parent (cdr (look_up_ident
		     (diana_get #$%as_constrained 'as_name))))
	   (momsrng (and parent (ct_send parent 'range))))
    (ct_send nutype 'initialize `(, #$%as_id
				  ,#$~res
				  ,momsrng
				  , #$%as_id))
    (let ((*activation*
	    (follow_alink_n_times
	      *activation*
	      (type_depth #$%as_id))))
      (set-iv adabe_activation *activation* 'locals
	      (cons
		(cons  #$%as_id nutype) 
		(get-iv adabe_activation *activation* 'locals) ;the locals slot.
		))))
  (ds_push (cons #$%as_id (first #$~res)) #$^types))



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Exceptions 


		;;;;;;;;;;;;
(def_diana_node dn_exception())		;do nothing at run time.
		;;;;;;;;;;;;



		;;;;;;;;
(def_diana_node dn_raise(exception_name handler handler_process propergatingp)
		;;;;;;;;

  (do ((i 0 (1+ i)))
      ((= i (second (arraydims *ds_cache*))))
    (let ((cache_entry (aref *ds_cache* i)))
      (%= (cache%activation cache_entry) nil)
      (%= (cache%node cache_entry) nil)
      (%= (cache%entry cache_entry) nil)))

  (%= #$~exception_name			  ;name of exception being raised.
      (cond
	((eq (diana_nodetype_get #$%as_name_void) 'dn_used_name_id)
	 (implode (cadr (diana_get #$%as_name_void 'lx_symrep))))
	(t
	 (find_propergated_exception_name pc))))
  (ct_push "raised by a raise statement" *exception_reason*)
  (ct_push #$~exception_name *exception_name*)
  ;;Before we raise the exception, check to see if there is advise for this
  ;;exception. If there is, call each advise function and THEN, raise the
  ;;exception.
  (let* ((excname #$~exception_name)
	 (advice_fcns (get excname 'ada_advise)))
    (mapc
      #'(lambda(af)
	  (funcall af excname nil))	  ;call the advice function.
      advice_fcns)
    ;(break look-at-exc)
    (%= #$~handler (find_exception_handler_for
		     (intern excname 'user)
		     (cond
		       (*exchandler* 
			(dynamic_mother *exchandler*))
		       (t pc))
		     *activation*)))
  ;(break foo)
  ;; before raising the exception, clear the cache.
  (do ((i 0 (1+ i)))
      ((= i (second (arraydims *ds_cache*))))
    (let ((cache_entry (aref *ds_cache* i)))
      (%= (cache%activation cache_entry) nil)
      (%= (cache%node cache_entry) nil)
      (%= (cache%entry cache_entry) nil)))

  (%= #$~handler_process
      (cond #|((eq *exchandler* (first #$~handler))
	     
	     (find_nodes_process (ct_send *activation* 'clink)
				 (first #$~handler)))|#
	    (t
	     (find_nodes_process *activation*  (first #$~handler)))))
  ;; to call an exception handler, create a handler node and pass control
  ;; to it in the right process.
  (let* ((hndler #$~handler)
	 (hndproc #$~handler_process)
	 (hannod (sc_diana dn_ct_exception_handler
			   as_stm_s (diana_get (second hndler) 'as_stm_s)
;			  ct_threadp (list pc);preserve the dynamic environment.
			   ct_threadp (list (first hndler))
			   ct_raising #$~exception_name	  ;name of the exception.
			   ct_id (gensym)
			   ct_resume    (first hndler))))
    (cond
      ((eq *activation* hndproc)	  ;if the process is the same.
       (%= *continuation* hannod))
      (t  (set-iv adabe_activation hndproc 'pc hannod)	  ;goto the handler node.
	  (%= *nuactivation* hndproc)	  ;switch to appropriate process.
	  )))
  )

       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun find_propergated_exception_name(pc)
       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  (cond
    ((eq (diana_nodetype_get pc) 'dn_ct_exception_handler) #$%ct_raising)
    (t (find_propergated_exception_name (dynamic_mother pc)))))


		;;;;;;;;;;;;;;;;;;;;;;;
(def_diana_node dn_ct_exception_handler()
		;;;;;;;;;;;;;;;;;;;;;;;
  (%= *exchandler* #$%ct_resume)
  (handle_exception_advise pc)
  (ds_call_diana #$%as_stm_s)
  (handle_exception_after_advise pc)
;  (break in-exception-handler)
  (%= *resume* #$%ct_resume)
  (ct_pop *exception_reason* )
  (ct_pop *exception_name* )
  (%= *exchandler* nil))

       ;;;;;;;;;;;;;;;;;;;;;;;
(defun handle_exception_advise (hanpc)
       ;;;;;;;;;;;;;;;;;;;;;;;
  (let* ((procname (intern
		     (implode
		       (cadr
			 (diana_get
			   (get-iv adabe_activation *activation* 'node)
			   'lx_symrep)))
		     'user))
	 (exceptname (diana_get hanpc 'ct_raising))
	 (aea (get procname 'ada_exception_advise)))
    (cond
      (aea				  ;if we have an advise function.
       (mapc
	 #'(lambda(aa)
	     (funcall aa procname exceptname))
	 aea)))))

       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun handle_exception_after_advise (hanpc)
       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (let* ((procname (intern
		     (implode
		       (cadr
			 (diana_get
			   (get-iv adabe_activation *activation* 'node)
			   'lx_symrep)))
		     'user))
	 (exceptname (diana_get hanpc 'ct_raising))
	 (aea (get procname 'ada_exception_after_advise)))
    (cond
      (aea				  ;if we have an advise function.
       (mapc
	 #'(lambda(aa)
	     (funcall aa procname exceptname))
	 aea)))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Generic specific diana nodes



		;;;;;;;;;;
(def_diana_node dn_generic ())
		;;;;;;;;;;

		;;;;;;;;;;;;;
(def_diana_node dn_generic_id ()
		;;;;;;;;;;;;;

      (ds_call_diana #$%sm_body)
      (ds_return_to_caller))


		;;;;;;;;;;;;;;;;
(def_diana_node dn_instantiation ()
		;;;;;;;;;;;;;;;;
  (ds_follow (first #$%sm_decl_s))	  ;elaborate the generic parameter dcls
  (ds_follow #$%as_name))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Task specific diana nodes.


		;;;;;;;;;;;;
(def_diana_node dn_task_decl(thistask)
		;;;;;;;;;;;;
  (let* ((asdes #$%as_id)
	 (taskq (ct_make_instance 'dt_task_type))
	 (pair (cons asdes taskq)))
    (ct_send taskq 'initialize nil)
    (ct_send taskq 'set-def_occurence asdes)
    (ct_send taskq 'set-sm_defn (extract_basetype asdes))
    (set-iv adabe_activation *activation*
	    'locals
	    (cons
	      pair
	      (get-iv adabe_activation *activation* 'locals)))
    (ct_send taskq 'set_val nil nil)
    (%= #$~thistask taskq))
  (ds_call_diana #$%as_task_def))

		;;;;;;;;;;;;
(def_diana_node dn_task_spec(dls dll nuar pqe hannod)
		;;;;;;;;;;;;
  (%= #$~dls #$%as_decl_s)
  (ds_label #$~dll)
  (ds_if #$~dls (ds_call_diana (ds_pop #$~dls)))
  (ds_if #$~dls (ds_goto #$~dll))
  
  ;;First of all, create a task handler node that will serve to extinguish
  ;;the task when it is completed.
  (let ((hannod (sc_diana dn_ct_task_handler
			  as_stm_s #$%sm_body
			  #|(let ((bdy (diana_get #$%as_id 'sm_body)))
			    (cond
			      ((eq (diana_nodetype_get bdy) 'dn_stub)
			       (diana_get
				 (diana_get #$%as_id 'sm_type_spec)
				 'sm_body))
			      (t bdy)))|#
			  ct_threadp (list pc)	  ;preserve the dynamic environment.
			  ct_cont nil
			  ct_id (gensym))))
    ;;create an activation for the task. Its C and A links are necessarily
    ;;the current process because of the way tasks are activated.
    (let* ((tpnl #$%ct_pnl)
	   (ar (make_activation_record tpnl tpnl)))
      (%= #$~nuar ar)			  ; make an empty AR.
      (set-iv adabe_activation ar 'pc hannod)
      (set-iv adabe_activation ar 'node hannod)
      (set-iv adabe_activation ar 'locals nil))	  ;there are no locals.yet.
    ;;now add the activation record to the task queue. pqe is assessed by
    ;;the handler node when it wants to destroy itself.
    ;(break what-is-thetask-name)
    (let ((tpqe (second
		  (ct_send *root_task_queue*
			   'add_task_to_priority_queue
			   *default_task_priority*;later use pragma's priority.
			   #$~nuar	  ;initialize the task to this process.
			   *current_task*
			    (implode
			      (cadr (diana_get
				      (ct_send #$^thistask 'def_occurence)
				      'lx_symrep)))))))
      (%= #$~pqe tpqe)			  ;this is the superior task.
      (ct_send tpqe 'make_runnable)	  ;make this task active.
      (ct_send tpqe 'set-terminated nil)  ;and bring him to life.
      (ct_send tpqe 'set-task_object #$^thistask)
      (ct_send #$^thistask 'set-tqe tpqe)
      (ds_push tpqe #$^mytasks)		  ;add this to the list of tasks in this
					  ;block.
      (ct_send #$~nuar 'set-taskinstance tpqe)
      (diana_put hannod tpqe 'ct_task_entry))
    )
)
  
		;;;;;;;;;;;;
(def_diana_node dn_task_body()
		;;;;;;;;;;;;

#|  
  (ct_format *userout* "In task body of ~A ~%"
	  (implode (cadr (diana_get #$%as_id 'lx_symrep))))
|#
;	(break in-dn-task-body)	
)
  
 

		;;;;;;;;;;;;;;;;;;
(def_diana_node dn_ct_task_handler(dead_p)
		;;;;;;;;;;;;;;;;;;

  (ds_if #$~dead_p 
         (progn
           (ct_send #$%ct_task_entry 'kill_yourself_and_inferiors)
           (ds_follow pc)))		  ;stage

;  (break in-task-handler-starting)
  (ds_call_diana #$%as_stm_s)		  ;pass control to the task body.stage

  (ct_send #$%ct_task_entry 'make_unrunnable)
  (ct_send #$%ct_task_entry 'delete_yourself_from_queue)
;  (break in-task-handler-finishing)
  (let ((taskent #$%ct_task_entry ))
    (ct_send taskent 'make_wait_for_inferiors
                            (ct_send taskent  'inferior_tasks)))
  (%= #$~dead_p t)			  ;I really am dead!
  (ds_follow pc)			  ;kill time while dying.
)

;;; The DELAY statement.
;;; Until we implement fixed point types, we will treat delay times
;;; specified as (integer) milliseconds.                                 ++


		;;;;;;;;
(def_diana_node dn_delay(res evaluatep)
		;;;;;;;;

  ;;first of all evaluate the delay.
  (%= #$~evaluatep t)
  (ds_follow #$%as_exp)
  ;;now wait for the specified time.
  (ct_send *current_task* 'wait_for_duration (car #$~res))
)

                ;;;;;;;;;;;;;
(def_diana_node dn_cond_entry(task ready_to_go_p)
                ;;;;;;;;;;;;;
  (%= #$~task (cdr (look_up_ident
		     (diana_get
		       (diana_get
			 (diana_get
			   (car (diana_get
				  #$%as_stm_s1
				  'as_list))
			   'as_name)
			 'sm_defn)
		       'as_name))))
  (let* ((eid (find_selected
	       (diana_get
		 (diana_get
		   (car (diana_get
			  #$%as_stm_s1
			  'as_list))
		   'as_name)
		 'sm_defn)))
	 (entobj (cdr (assq eid (ct_send #$~task 'current_value)))))
    (cond ((and entobj
		(ct_send entobj 'accesses_waiting))
	   (%= #$~ready_to_go_p t))))
  (ds_if #$~ready_to_go_p
	 (ds_call_diana #$%as_stm_s1)
	 (ds_call_diana #$%as_stm_s2)))

;;; The ACCEPT statement.


		;;;;;;;;;
(def_diana_node dn_accept(entry rendez accepting)
		;;;;;;;;;
  (let ((ent (cdr (assq (diana_get #$%as_name 'sm_defn)
			(ct_send
			  (ct_send *current_task* 'task_object)
			  'current_value)))))
    (%= #$~entry ent)
    (ds_if (not (or (ct_send  ent  'accesses_waiting)  #$~accepting))
	   (progn
	     #|	   (ct_format *userout* "waiting on accept ~A ~A~%"
		      (implode (cadr (diana_get #$%as_name 'lx_symrep)))
		      #$%ct_id)|#
	     (ct_send *current_task* 'make_unrunnable)	  ;temporary permanant wait.
	     (ct_send ent 'set-entry_waiting *current_task*)
	     (%= #$~accepting t)
;	   (break sleep-while-waiting-for-entry)
	     (ds_follow pc))))
  (ds_break);stage

#|	 (break entry-read-to-go)|#
  (let ((ent #$~entry))
    (%= #$~rendez (first (ct_send ent 'accesses_waiting)))
    (ct_send ent
	     'set-accesses_waiting (cdr (ct_send ent 'accesses_waiting))))
  (set-iv adabe_activation *activation* 'locals
	   (append (get-iv adabe_activation (second #$~rendez) 'locals)
		   (get-iv adabe_activation *activation* 'locals)))
;  (break about-to-make-rendezvous)
  (ds_follow #$%as_stm_s)  ;;pass control to rendezvous. stage

  (ct_send (first #$~rendez) 'make_runnable)
;  (break end-of-rendezvous)
)

                ;;;;;;;;;;;
(def_diana_node dn_entry_id(entry returned)
                ;;;;;;;;;;;
  (ds_if #$~returned
	 (progn
;	   (break back-from-entry)
	   (ds_return_to_caller)))	  ;stage

  (let ((ent (cdr (assq
		    (diana_get
		      (diana_get
			(diana_get
			  (get-iv adabe_activation
				  (get-iv adabe_activation *activation* 'clink)
				  'pc)
			  'as_name)
			'sm_defn)
		      'as_designator_char)
		    (let* ((*activation* (ct_send *activation* 'clink))
			   (pc (ct_send *activation* 'pc)))
		      (ct_send #$~task 'current_value))))))
    (%= #$~entry ent)
;  (break about-to-initiate-entry)
;  (ct_format *userout* "entering ~A~%" #$%ct_id)
    (%= #$~returned t)
    (ct_send ent
	     'add_me_to_the_access_waiting_queue *current_task* *activation*))
  (ds_return_to_caller))

       ;;;;;;;;;;;;;;;;;;;;;;;
(defun dead_or_dying_offspring (offspring me)
       ;;;;;;;;;;;;;;;;;;;;;;;
  (do ((brother offspring (cdr brother)))
      ((null brother) t)
    (cond ((and (neq me (car brother))
		(null (ct_send (car brother) 'terminated)))
	   ;++needs more to detect dying offspring
	   (return nil)))))

       ;;;;;;;;;;;;;
(defun ready_to_go_p (stms)
       ;;;;;;;;;;;;;
  (let* ((selecttype (first (diana_get stms 'as_list))))
    (ct_selectq (diana_nodetype_get selecttype)
		(dn_delay
		  (lose
		    'be_dsis
		    'ready_to_go_p
		    '("delay statements in selects not supported at present")))
		(dn_entry (lose 'be_esis 'ready_to_go_p))
		(dn_accept
		  (let* ((eid (diana_get
				(diana_get selecttype 'as_name) 'sm_defn))
			 (task (ct_send
				 (ct_send *activation* 'taskinstance)
				 'task_object))
			 (entry (cdr (assq eid
					   (ct_send task 'current_value))))
			 (queue (ct_send entry 'accesses_waiting)))
		    (cond (queue stms))))		    
		(dn_terminate ;(break in-ready_to_go-terminate)
		  ;(break in-terminate)
		  ;(ct_send *current_task* 'kill_yourself_and_inferiors)
		  (let* ((mom (ct_send *current_task* 'superior_task))
			 (menopausalp
			   (ct_send mom 'waiting_for_inferiors_to_finish))
			 (offspring (ct_send mom 'inferior_tasks)))
		    (cond
		      ((and menopausalp
			    (dead_or_dying_offspring offspring *current_task*))
		       (ct_send *current_task* 'kill_yourself_and_inferiors))))
		      
		  nil))))
	 

                ;;;;;;;;;
(def_diana_node dn_select(chosen csc csl picked)
                ;;;;;;;;;
  ;;get the candidate set =>chosen
  (ds_follow (first #$%as_select_clause_s))	  ;stage

  (%= #$~chosen (nreverse *_*))
  (%= #$~csc #$~chosen)
  (ds_label #$~csl)			  ;stage

  (ds_if #$~csc
	 (%= #$~picked (ready_to_go_p (first #$~csc))))	  ;stage

  (ds_pop #$~csc)
  (ds_if (and #$~csc (not #$~picked))
	 (ds_goto #$~csl))		  ;stage

  
  (ds_if #$~picked
	 (ds_call_diana #$~picked)
	 (ds_if #$%as_stm_s
		(ds_call_diana #$%as_stm_s))));(break go-do-the-else-part)))

                ;;;;;;;;;;;;;;;;
(def_diana_node dn_select_clause(res evaluatep referencep)
                ;;;;;;;;;;;;;;;;
  (%= #$~evaluatep t)
  (%= #$~res `(,*ct_ada_true*))			  ;assume t for void case
  ;;evaluate the when part 
  (ds_follow #$%as_exp_void)
  ;;if the when part yeided true add to the candidate set
  (cond ((eq *ct_ada_true* (first #$~res))
	 (ds_push #$%as_stm_s #$^chosen))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Subprogram declaration /calls


       ;;;;;;;;;;;;;
(defun strip_renames(id)
       ;;;;;;;;;;;;;
  (cond
    ((and (not
	    (eq
	      (diana_nodetype_get id)
	      'dn_entry_id))
	  (eq (diana_nodetype_get
		(diana_get id 'sm_body))
	      'dn_rename))
     (strip_renames
       (diana_get
	 (diana_get id 'sm_body)
	 'as_name))
     )
    (t id)))

		;;;;;;;;;;;;;;;;
(def_diana_node dn_function_call(funres name body evaluatep res referencep apl epl
		;;;;;;;;;;;;;;;;

					bltinp func  nuar invar seres
					procname aa rtnval constraint
					basetypespec dscrmt_constraints
					dscrmt_vars indexlist dscrmts
					fpl ueparams eparams pils compobj proto)
    (%= #$~seres #$%sm_value)
    (ds_if #$~seres
	   (progn			  ;return the result.
	     (cond (#$^evaluatep (ds_push #$~seres #$^res))	
		   (t            (ds_push #$~seres #$^name)))
	     (ds_exit)))
    (%= #$~invar t)  
    (%= #$~apl
	(diana_get #$%sm_normalized_param_s 'as_list)) ;get the parameters.
    #|(%= #$~fpl (mapcar
		 #'extract_basetype
		 (diana_get (diana_get pc 'sm_normalized_param_s) 'as_list)))|#
    (let* ((smdef (diana_get #$%as_name 'sm_defn))
	   (rmsel (cond ((eq (diana_nodetype_get smdef) 'dn_selected)
			 (diana_get (find_selected smdef) 'sm_defn))
			(t smdef)))
	   (spec (diana_get rmsel 'sm_spec))
	   (aspar (and spec (diana_get
			      spec
			      'as_param_s))))
      (%= #$~fpl (mapcar
		   #'(lambda(dn)
		       (diana_get
			 (car (diana_get dn 'as_id_s))
			 'sm_obj_type))
		   aspar)))
    (ds_label #$~epl)			  ;evaluate parameters loop.stage

    (%= #$~referencep t)
    (%= #$~evaluatep nil)
    (ds_if #$~apl			  ;if there are parameters to evaluate.
	   (let ((next_parameter (ds_pop #$~apl)))	     
	     (ds_call_diana next_parameter))) ;stage

    ;; find the parameter constraints indices and prototypes if any.
    (let ((tfpl #$~fpl))
      (ds_if tfpl
	   (let ((bts
		   (cond ((car tfpl)(ds_find_base_type_spec (car tfpl))))))
	     (cond ((is_dscrmt_record bts)
		    (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
		    (%= #$~dscrmt_vars (dscrmt_record%vars bts))
		    (%= bts (dscrmt_record%record *_*))))
	     (%= #$~basetypespec bts))))	  ;stage
;    (ds_break)
  (let ((dc #$~dscrmt_constraints))
    (%= #$~evaluatep t)  
    (%= #$~res nil)			  ;index ranges will be
					  ; collected in res.
    (ds_if dc				  ;collect dscrmts if any.
	   (ds_call_diana dc)))
    (ds_break)			  ;stage

;  (break dn_var)
  (%= #$~constraint nil)
  (let ((bts #$~basetypespec))
    (ds_if (and #$~fpl (diana_nodep bts)  )
	   (ds_call_diana bts)))	  ;list=>diana.
  (ds_break)			  ;stage
  
  
  (let ((il (or (nreverse #$~res) #$~constraint)))
    (ds_push il #$~pils)		  ;add index to ordered list of parameters.
    (%= #$~indexlist il))
  (ds_pop #$~fpl)
    ;; continue to iterate over the actuals.
    (ds_if #$~apl (ds_goto #$~epl));stage


    (%= #$~ueparams #$~name)		  ;the unevaluated parameters.
    (%= #$~evaluatep t)
    (%= #$~procname
	(intern (implode (cadr (diana_get #$%as_name 'lx_symrep)))
		'user))
    (%= #$~aa (get #$~procname 'ada_advise)) ;Ada advice functions.
    (ds_if
      (or
	(eq
	  (diana_nodetype_get
	    (diana_get (diana_get #$%as_name 'sm_defn) 'sm_body))
	  'dn_predefined_simple_function)
	(and (eq
	       (diana_nodetype_get
		 (diana_get (diana_get #$%as_name 'sm_defn) 'sm_body))
	       'dn_rename)
	     (eq
	       (diana_nodetype_get
		 (diana_get
		     (diana_get
		       (diana_get (diana_get #$%as_name 'sm_defn) 'sm_body)
		       'as_name)
		   'sm_body))
	       'dn_predefined_simple_function)))
      (let ((res (funcall (cond ((eq
				   (diana_nodetype_get
				     (diana_get
				       (diana_get #$%as_name 'sm_defn)
				       'sm_body))
				   'dn_rename)
				 (diana_get
				   (diana_get
				       (diana_get
					 (diana_get
					   (diana_get #$%as_name 'sm_defn)
					   'sm_body)
					 'as_name)
				     'sm_body)
				   'ct_lisp_func))
				(t (diana_get
				     (diana_get
				       (diana_get #$%as_name 'sm_defn)
				       'sm_body)
				     'ct_lisp_func)))
			  (nreverse
			    (mapcar
			      #'(lambda(pn)
				  (cond
				    ((instancep pn) (ct_send pn 'get_val nil))
				    (t pn)))
			      #$~name)))))
;	(ct_send #$~rtnval 'set_val res)
	;; return the function result.
	(cond (#$^evaluatep (ds_push res #$^res))	
	      (t            (ds_push res #$^name)))
	(ds_exit)))
    ;; To call a user defined function --
    ;; 1. Evaluate the normalized parameters. (returns alist of parameters)
    ;; 2. Create New activation record for this function.
    ;; 3. Put parameters on to the locals slot for the new AR.
    ;; 4. Put the #$~body onto the pc and code slots.
    ;; 5. activation record %= new activation record.
    ;; 6. follow the body.
    ;; 7. Pop the AR (follow click).
    (let ((bdy (diana_get #$%as_name 'sm_defn)))
      (%= #$~body bdy)			  ; body is a dn_function_id.
      (let ((ar 
	      (make_activation_record
		#$%ct_pnl
		(diana_get (strip_renames
			     (subprog_bit bdy))
			     'ct_pnl)))); make an empty AR.
	(%= #$~nuar ar)
      (set-iv adabe_activation ar 'pc bdy)	  ; start function at the start.
      (set-iv adabe_activation ar 'node  bdy)
	(let ((nam #$~name)
	      (pc bdy)
	      (*activation* ar))
	  (set-iv adabe_activation ar 'locals 
		 (buildparamlocals 
		   (nreverse (mapcar
			       #'(lambda(pn)
				   (cond
				     ((instancep pn) (ct_send pn 'get_val nil))
				     (t pn)))
			       nam))  ; evaluated actuals.
		   (diana_get
		     (let ((id (strip_renames (subprog_bit bdy))))
		       (or (diana_get id 'ct_spec)
			   (diana_get id 'sm_spec)))
		     'as_param_s); formals.
		   )))))			  ; setup the initial locals.
    (let ((bts (ds_find_base_type_spec #$%sm_exp_type) ))
      (cond ((is_dscrmt_record bts)
	     (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
	     (%= #$~dscrmt_vars (dscrmt_record%vars bts))
	     (%= bts (dscrmt_record%record *_*))))
      (%= #$~basetypespec bts))
    (%= #$~res nil)			  ;index ranges will be
           				  ; collected in res.
    (ds_if #$~dscrmt_constraints		  ;collect dscrmts if any.
	   (ds_call_diana #$~dscrmt_constraints));stage

    (let ((bts #$~basetypespec))
      (ds_if (diana_nodep bts)
	   (ds_call_diana bts)))    ;list=>diana.
    (ds_break) ;stage

    (%= #$~indexlist (reverse #$~res))	  ; find indexlist.(if any)
    (let* ((returntype #$%sm_exp_type)
	   (groupbasetype (basetype returntype))
	   (grouptype returntype)
	   (nuobj (ct_make_instance	  ; create return variable.
		     (type_builder groupbasetype)
		     'ada_name nil
		     'ada_index nil)))
	(ct_send nuobj 'initialize
		 (pinitfun groupbasetype grouptype nil #$~indexlist))
	(%= #$~rtnval nuobj))
    (let ((ar #$~nuar)
	  (bdy #$~body)) 
      (cond
	(#$~aa				  ;if there is Ada Advise
	 (let ((*activation* ar))
	   (mapc
	     #'(lambda(af)
		 (funcall af #$~procname
			  (reverse #$~ueparams))) ;#$~res
	     #$~aa))))			  ;apply it to the evaluated arguments.
      (%= *nuactivation* ar))		  ; driver will switch in nu activation record
				; on the next cycle of the virtual machine.
    (ds_break)				  ;stage

    (%= #$~aa (get #$~procname 'ada_after_advise)) ;Ada advice functions.
    (cond ((and (not (eq (diana_nodetype_get
			   (diana_get #$~body 'sm_body))
			 'dn_predefined_function))
		(not #$~funres))
	   (ada_raise '|program_error| "return statement not executed")))
    (cond
      (#$~aa			;if there is Ada Advise
       (let ((*activation* #$~nuar))
	 (mapc
	   #'(lambda(af)(funcall af #$~procname (list #$~funres)))
	   #$~aa))))			  ;apply it to the evaluated arguments.
    ;; return the function result.
    (cond (#$^evaluatep (ds_push #$~funres #$^res))	
          (t            (ds_push #$~funres #$^name)))
)


		;;;;;;;;;;;;;;;;;
(def_diana_node dn_procedure_call(body evaluatep referencep procname aa apl epl
		;;;;;;;;;;;;;;;;;
				       basetypespec dscrmt_constraints invar
				       dscrmt_vars indexlist constraint task
				       fpl res nuar tpnl dpnl name dscrmts
				       ueparams eparams pils compobj proto)
    ;; To call a procedure --
    ;; 1. Evaluate the normalized parameters. (returns alist of parameters)
    ;; 2. Create New activation record for this procedure.
    ;; 3. Put parameters on to the locals slot for the new AR.
    ;; 4. Put the #$~body onto the pc and code slots.
    ;; 5. activation record %= new activation record.
    ;; 6. follow the body.
    ;; 7. Pop the AR (follow clink).
    (%= #$~invar t)
    (%= #$~apl
	(diana_get #$%sm_normalized_param_s 'as_list)) ;get the parameters.
    #|(%= #$~fpl (mapcar
		 #'extract_basetype
		 (diana_get (diana_get pc 'sm_normalized_param_s) 'as_list)))|#
    (let* ((smdef (diana_get #$%as_name 'sm_defn))
	   (rmsel (cond ((eq (diana_nodetype_get smdef) 'dn_selected)
			 (diana_get (find_selected smdef) 'sm_defn))
			(t smdef)))
	   (spec (diana_get rmsel 'sm_spec))
	   (aspar (and spec (diana_get
			      spec
			      'as_param_s))))
      (%= #$~fpl (mapcar
		   #'(lambda(dn)
		       (diana_get
			 (car (diana_get dn 'as_id_s))
			 'sm_obj_type))
		   aspar)))
    (ds_label #$~epl)			  ;evaluate parameters loop.stage

    (%= #$~referencep t)
    (%= #$~evaluatep nil)
    (ds_if #$~apl			  ;if there are parameters to evaluate.
	   (let ((next_parameter (ds_pop #$~apl)))
	     (ds_call_diana next_parameter)))	  ;stage

    ;; find the parameter constraints indices and prototypes if any.
    (let ((tfpl #$~fpl))
      (ds_if tfpl
	     (let ((bts 
		     (cond ((car tfpl)(ds_find_base_type_spec (car tfpl))))))
	       (cond ((is_dscrmt_record bts)
		      (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
		      (%= #$~dscrmt_vars (dscrmt_record%vars bts))
		      (%= bts (dscrmt_record%record *_*))))
	       (%= #$~basetypespec bts))))

  (cond ((eq (diana_nodetype_get  (diana_get #$%as_name 'sm_defn)) 'dn_selected)
	 (%= #$~task (cdr (look_up_ident
		       (diana_get (diana_get #$%as_name 'sm_defn) 'as_name)
			    
		       )))))


#| this might be the best way oneday.
  (%= #$~evaluatep t)
  (ds_if (eq (diana_nodetype_get (diana_get #$%as_name 'sm_defn)) 'dn_selected)
	 (ds_call_diana (diana_get #$%as_name 'sm_defn)))
  (%= #$~task (ds_pop #$~res))
  (break look-at-task)
|#

  (%= #$~evaluatep t)
  (%= #$~res nil)			  ;index ranges will be
           				  ; collected in res.
  (let ((dc #$~dscrmt_constraints))
    (ds_if dc				  ;collect dscrmts if any.
	   (ds_call_diana dc)))
    (ds_break);stage


  (%= #$~constraint nil)
  (let ((bts #$~basetypespec))
    (ds_if (and #$~fpl (diana_nodep bts)  )
	   (ds_call_diana bts)))	  ;list=>diana.
  (ds_break)				  ;stage

  (let ((il (or (reverse #$~res) #$~constraint)))	  ; find indexlist.(if any)
    (ds_push il #$~pils)		  ;add index to ordered list of parameters.
    (%= #$~indexlist il))
  (ds_pop #$~fpl)
    ;; continue to iterate over the actuals.
    (ds_if #$~apl (ds_goto #$~epl))	  ;stage

;  (break wot-we-got)
    (%= #$~eparams
	(let ((formals
		(extract_formal_id_s
		  (let ((spec
			  (cond
			    ((and
			       (not
				 (eq
				   (diana_nodetype_get
				     (subprog_bit
				       (diana_get #$%as_name 'sm_defn)))
				   'dn_entry_id))
			       (diana_get
				     (subprog_bit
				       (diana_get #$%as_name 'sm_defn))
				     'sm_body)
			       (eq (diana_nodetype_get
				   (diana_get
				     (subprog_bit
				       (diana_get #$%as_name 'sm_defn))
				     'sm_body))
				   'dn_rename))
			     ;(break in-dn-proc)
			     (diana_get
				 (diana_get
				   (diana_get
				     (subprog_bit
				       (diana_get #$%as_name 'sm_defn))
				     'sm_body)
				   'as_name)
			       'sm_spec))
			    (t (diana_get
				 (subprog_bit
				   (diana_get #$%as_name 'sm_defn))
				 'sm_spec)))))
		    (and spec (diana_get spec 'as_param_s))))))
	  (mapcar
	    #'(lambda(pn fp)		  ;car fp is a dn_in/out/in_out_id node
		(cond
		  ((and (instancep pn)
			(not (eq (diana_nodetype_get (car fp)) 'dn_out_id)))
		   (ct_send pn 'get_val nil))
		  (t pn)))
	    #$~name (reverse formals))))	  ;dereference the parameters.
    (%= #$~ueparams #$~name)		  ;save the unevaluated ones for OUT
    (%= #$~procname (intern
		      (implode (cadr
				 (diana_get #$%as_name 'lx_symrep)))
		      'user))
    (%= #$~aa (get #$~procname 'ada_advise)) ;Ada advice functions.
    (let* ((bdy
	    (subprog_bit
	      (diana_get #$%as_name 'sm_defn))) ; body is a dn_proc_id node.
	  ;;now, if this is a dn_subprogram_decl, we really want its as_designator.
	  (ar
	    (make_activation_record
	      #$%ct_pnl
	      (diana_get (strip_renames
			   (subprog_bit bdy))
			 'ct_pnl))))	  ; make an empty AR.
      (%= #$~nuar ar)
      (%= #$~body bdy)
      (set-iv adabe_activation ar 'pc bdy)	  ; start procedure at the start.
      (set-iv adabe_activation ar 'node  bdy)

      (let ((epars #$~eparams)
	    (asnam #$%as_name)
	    (pc bdy)
	    (*activation* ar))
	(set-iv adabe_activation ar 'locals 
	       (buildparamlocals 
		 (reverse epars)	  ; evaluated actuals.
		 (let ((spec
		     (let ((id (strip_renames (subprog_bit
					  (diana_get asnam 'sm_defn)))))
		       (or (diana_get id 'ct_spec)
			   (diana_get id 'sm_spec)))))
		   (and spec (diana_get spec 'as_param_s)))  ; formals.
		 )))			  ; setup the initial locals.
      (cond
	(#$~aa				  ;if there is Ada Advise
	 (let ((*activation* ar)) 
	   (mapc
	     #'(lambda(af)
		 (funcall af #$~procname (reverse #$~ueparams)))
	     #$~aa))))			  ;apply it to the evaluated arguments.
	     (%= *nuactivation* ar))	 ;driver will switch in nuactivation record
				; on the next cycle of the virtual machine.
;    (break "about to invoke a new process")
    (ds_break)				  ;stage


;    (break "returned from process")
;;;now that we have returned from the procedure, lets copy back any out 
;;;parameters.
    (%= #$~evaluatep nil)
    (%= #$~referencep t)	;find the origins of the variables.
    (%= #$~name nil)
;;    (ds_follow (first #$%as_param_assoc_s)) ;put result onto #$~name.stage

    (%= #$~aa (get #$~procname 'ada_after_advise)) ;Ada advice functions.
    (%= #$~name
	(copy_back_out_parameters
;      #$%as_param_assoc_s       ;the actual (reference) parameters.
	  (reverse #$~ueparams)		  ;the actual parameter references.
	  (let ((spec
		  (let ((id (strip_renames (subprog_bit
					  (diana_get #$%as_name 'sm_defn)))))
		       (or (diana_get id 'ct_spec)
			   (diana_get id 'sm_spec)))))
	    (and spec (diana_get spec 'as_param_s)))	  ; formal parameters
	  #$~nuar			  ;the activation record.
	  ))
    (cond
      (#$~aa			;if there is Ada Advise
       (let ((*activation* #$~nuar))
	 (mapc
	   #'(lambda(af)(funcall af #$~procname (reverse #$~ueparams)))
	   #$~aa))))			  ;apply it to the evaluated arguments.
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Conditional Statements


		;;;;;;;
(def_diana_node dn_case(expval res evaluatep flag)
		;;;;;;;

    (%= #$~evaluatep t)
    (ds_follow #$%as_exp)			; pushed result to #$~res
    (%= #$~expval (ds_pop #$~res))
    (ds_follow  #$%as_alternative_s))		; search for appropriate
						; 'when'


		;;;;;;;;;;;;;;;;
(def_diana_node dn_alternative_s()
		;;;;;;;;;;;;;;;;

    (ds_follow (first #$%as_list)))


		;;;;;;;;;;;;;;
(def_diana_node dn_alternative(res)
		;;;;;;;;;;;;;;

    (ds_if #$^flag (ds_exit))			; exit if found already.
    (ds_follow #$%as_choice_s)			; look for maching choice.stage

    (let ((exval  #$^expval))
      (mapc
	#'(lambda(ch)
	    (ds_if (consp ch)
		   (cond ((and (greaterp (1+ (coerce_int exval))
					 (coerce_int (first ch)))
			       (lessp    (1- (coerce_int exval))
					 (coerce_int (second ch))))
			  (%= #$^flag t)))
		   (cond ((or (eq ch t)(equal exval ch))
			  (%= #$^flag t)))))
	#$~res))
;    (break in-alternative)
    (ds_if #$^flag (ds_follow #$%as_stm_s) (ds_exit))
)


		;;;;;;;;;
(def_diana_node dn_others()
		;;;;;;;;;

    (ds_push t #$^res))			; this one always wins!


		;;;;;;;;;;;
(def_diana_node dn_choice_s()
		;;;;;;;;;;;

    (ds_follow (first #$%as_list)))


		;;;;;
(def_diana_node dn_if(res)
		;;;;;

    (%= #$~res nil)				; set to t upon completion.
    (ds_follow (first #$%as_list)))		; sucessful cond will return.


		;;;;;;;;;;;;;;
(def_diana_node dn_cond_clause(evaluatep)
		;;;;;;;;;;;;;;

    (ds_if (eq *ct_ada_true* (first #$~res)) (ds_exit))
    (%= #$~evaluatep t)
    (ds_push  *ct_ada_true* #$~res)		; assume t for void case.
    (ds_follow #$%as_exp_void)			; evaluate the expression.
    (ds_if (eq *ct_ada_true* (first #$~res)) (ds_follow #$%as_stm_s)(ds_exit))
    						; if true evaluate stm's
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Control/Iteration Statements


		;;;;;;;
(def_diana_node dn_exit (res evaluatep)
		;;;;;;;

  (%= #$~evaluatep t)				;evaluate the condition.
  (%= #$~res `(,*ct_ada_true*))			;assume that we should leave.
  (ds_follow #$%as_exp_void)
  (ds_if (eq *ct_ada_true* (first #$~res))	; t if we should exit loop.
	 (let ((enclp (cond ((eq (diana_nodetype_get #$%as_name_void)
				 'dn_used_name_id)
			     (diana_get
			       (diana_get #$%as_name_void 'sm_defn)
					'sm_stm))
			    (t (find_closest 'dn_loop pc)))));find loop.
;	   (break in-exit)
	   ;reset the cache
	   (do ((i 0 (1+ i)))
	       ((= i (second (arraydims *ds_cache*))))
	     (let ((cache_entry (aref *ds_cache* i)))
	       (%= (cache%activation cache_entry) nil)
	       (%= (cache%node cache_entry) nil)
	       (%= (cache%entry cache_entry) nil)))
	   (%= *resume* (exit_route enclp)))));exit from it.

;;; Find the closest superior 'node' of 'at'

       ;;;;;;;;;;;;
(defun find_closest(node at)
       ;;;;;;;;;;;;

  (let ((mom (dynamic_mother at)))
    (cond
      ((null mom)(lose 'be_enil 'find_closest
		       `("Error - exit statement not inside a loop")
		       `("Error - exit statement not inside a loop")))
      ((eq (diana_nodetype_get mom) 'dn_ct_exception_handler)
       (find_closest node (diana_get mom 'ct_resume)))
      ((eq (diana_nodetype_get mom) node) mom)
      (t (find_closest node mom)))))

;;; Find the correct exit path from a diana node.

       ;;;;;;;;;;
(defun exit_route(pc)
       ;;;;;;;;;;

  (let ((called_by (nodestagerec%caller
		     (adabe_nodestage_get *activation* pc))))
    (cond
      (called_by called_by)			;we were invoked as a diana proc
      (t #$%ct_cont))))


		;;;;;;;
(def_diana_node dn_loop	(loopvar eolp loopphase res lp)
		;;;;;;;

    ; eolp=t means loop, eolp=nil means not.
    (%= #$~eolp t)				       ; initially loop.
    (%= #$~loopphase 'initialize)		       ; start of loop.
    (ds_follow #$%as_iteration)			       ; preloop test/init.
    (%= #$~loopphase 'iterate)			       ; enter iteration
						       ; cycle.
    (ds_label #$~lp)
;    (ds_follow #$%as_stm_s)
    (ds_if (null #$~eolp)
	(progn
	  (ds_undeclare (car #$~loopvar))
	  (ds_exit))					; end of loop.
	(ds_follow #$%as_stm_s))
    (ds_follow #$%as_iteration)				; loop test
    (ds_goto #$~lp)
)



		;;;;;;
(def_diana_node dn_for(evaluatep basetype constraint)
		;;;;;;

  (%= #$~evaluatep t)
  (ds_if (eq #$~loopphase 'initialize)
	 (ds_call_diana (cond ((eq (diana_nodetype_get #$%as_dscrt_range)
				   'dn_used_name_id)
			       (diana_get  #$%as_dscrt_range 'sm_defn))
			      ((eq (diana_nodetype_get #$%as_dscrt_range)
				   'dn_constrained)
			       (diana_get  #$%as_dscrt_range 'as_constraint))
			      (t  #$%as_dscrt_range))))	  ; find range.stage

  (ds_follow #$%as_id)			  ; find loop id.stage

  (ds_if (eq #$~loopphase 'initialize)
	 (ds_declare (car #$~loopvar)
		     (let ((flv (first (first #$~res))))
			   (cond
			     ((numberp flv) (type_builder '|integer|))
			     ((and (diana_nodep flv)
				   (memq (diana_nodetype_get flv)
						  '(dn_enum_id dn_def_char)))
			      (type_builder '|enumeration|))
			     ((null #$~res)
			      (%=  #$~res #$~constraint)
			      (type_builder
				(basetype (extract_basetype (first #$^loopvar)))))
			     (t (lose 'be_ubif 'diana_node_dn_for
				      ()  ;let the lusers work it out for themselves
				      `("unknown basetype in for")))))
		     nil))
					  ; variable.stage

  (let ((carlpvar (car #$~loopvar))
	(result  #$~res))
    (cond
      ((eq #$~loopphase 'initialize)	  ;check that we really want to iterate.
       (%= #$^eolp (le (coerce_int (first (first result)))
		       (coerce_int (second (first result))))))
      (t
       (ds_if (ge (coerce_int (ds_valof carlpvar))
		  (coerce_int (second (first result))))	  ; end of iteration?
	      (%= #$^eolp nil)		  ; yes.
	      (%= #$^eolp t))))		  ; no..continue.
    (ds_if (eq #$~loopphase 'initialize)
	   (progn
	     (ct_send (cdr (look_up_ident carlpvar))
			   'initialize
			   (list
			     (extract_basetype
			       (diana_get (car #$~loopvar) 'sm_defn))
			     nil
			     nil
			     (diana_get (car #$~loopvar) 'sm_defn)))
	     (ds_update carlpvar nil
			(first (first result))))	  ; initialize loopvar.
	   (cond (#$~eolp (ds_succ carlpvar)))))
  (ds_exit)
  )

                ;;;;;;;;;
(def_diana_node dn_rename ()
                ;;;;;;;;;
  
    (ds_if
      (let ((smdef (diana_get #$%as_name 'sm_defn)))
	(cond ((and smdef
		    (eq
		      (diana_nodetype_get
			smdef)
		      'dn_package_id)) nil)
	      (t t)))
      (ds_call_diana (diana_get #$%as_name 'sm_body))))

		;;;;;;;;;;
(def_diana_node dn_reverse(evaluatep basetype constraint)
		;;;;;;;;;;

  (%= #$~evaluatep t)
  (ds_if (eq #$~loopphase 'initialize)
	 (ds_call_diana (cond ((eq (diana_nodetype_get #$%as_dscrt_range)
				   'dn_used_name_id)
			       (diana_get  #$%as_dscrt_range 'sm_defn))
			      ((eq (diana_nodetype_get #$%as_dscrt_range)
				   'dn_constrained)
			       (diana_get  #$%as_dscrt_range 'as_constraint))
			      (t  #$%as_dscrt_range))))	  ; find range.stage

  (ds_follow #$%as_id)			  ; find loop id.stage

  (ds_if (eq #$~loopphase 'initialize)
	 (ds_declare (car #$~loopvar)
		     (let ((flv (second (first #$~res))))
			   (cond
			     ((numberp flv) (type_builder '|integer|))
			     ((and (diana_nodep flv)
				   (memq (diana_nodetype_get flv)
						  '(dn_enum_id dn_def_char)))
			      (type_builder '|enumeration|))
			     (t (lose 'be_ubif 'diana_node_dn_reverse
				      ()  ;let the lusers work it out for themselves
				      `("unknown basetype in reverse")))))
		     nil))
					  ; variable.stage

  (let ((carlpvar (car #$~loopvar))
	(result #$~res))
    (cond
    ((eq #$~loopphase 'initialize)	  ;check that we really want to itterate.
     (%= #$^eolp (le (coerce_int (first (first result)))
		     (coerce_int (second (first result))))))
    (t
     (ds_if (le (coerce_int (ds_valof carlpvar))
		(coerce_int (first (first result))))	  ; end of iteration?
	    (%= #$^eolp nil)		  ; yes.
	    (%= #$^eolp t))))		  ; no..continue.
  (ds_if (eq #$~loopphase 'initialize)
	 (progn
	   (ct_send (cdr (look_up_ident carlpvar))
			   'initialize
			   (list
			     (extract_basetype
			       (diana_get (car #$~loopvar) 'sm_defn))
			     nil
			     nil
			     (diana_get (car #$~loopvar) 'sm_defn)))  
	 (ds_update carlpvar nil (second (first result))))  ; initialize loopvar.
	 (cond (#$~eolp (ds_pred carlpvar)))))
  (ds_exit)
  )


		;;;;;;;;
(def_diana_node dn_while(res evaluatep)	  ;
		;;;;;;;;

    (%= #$~evaluatep t)
    (ds_follow #$%as_exp)				; eval condition.
    (%= #$^eolp (eq *ct_ada_true* (first #$~res)))	; return value.
)



		;;;;;;;;;;;;;;;
(def_diana_node dn_used_bltn_op()
		;;;;;;;;;;;;;;;

    (%= #$~bltinp t)				; report build in op.
    (%= #$~func (mapop #$%sm_operator))		; return lisp function.
)

                ;;;;;;;;;
(def_diana_node dn_binary (evaluatep res)
                ;;;;;;;;;
  (%= #$~evaluatep t)
  (ds_follow #$%as_exp1)		  ;evaluate the first part stage

  (ds_if (and
	   (eq *ct_ada_true* (first #$~res))
	   (eq (diana_nodetype_get #$%as_binary_op) 'dn_or_else))
	 ;;return the true result to caller
	 (progn (cond (#$^evaluatep (ds_push *ct_ada_true* #$^res))
		      (t (ds_push *ct_ada_true* #$^name)))
		(ds_exit))
	 ;;otherwise try the other leg.
	 (ds_if (not
		  (and
		    (eq *ct_ada_false* (first #$~res))
		    (eq (diana_nodetype_get #$%as_binary_op) 'dn_and_then)))
		(ds_follow #$%as_exp2)))  ;stage

; (break mumf)
  (cond (#$^evaluatep (ds_push (first #$~res)  #$^res))
		      (t (ds_push  (first #$~res) #$^name))))

		;;;;;;;;;;;;;;;;
(def_diana_node dn_parenthesized()
		;;;;;;;;;;;;;;;;

    (ds_follow #$%as_exp))			; evaluate embedded exp.



		;;;;;;;;
(def_diana_node dn_range(res evaluatep)
		;;;;;;;;

  (%= #$~evaluatep t)			  ; evaluate bounds.
  (ds_call_diana #$%as_exp2)		  ; compute last.
  (ds_call_diana #$%as_exp1)		  ; compute first.
  (ds_push  (list (ds_pop #$~res)(ds_pop #$~res)) #$^res)
  )


		;;;;;;;;;;;;;;;
(def_diana_node dn_iteration_id()
		;;;;;;;;;;;;;;;

    (ds_push pc #$~loopvar) 		; return loop id.
)


		;;;;;;;;;;;;;;;;;;
(def_diana_node dn_subprogram_decl()
		;;;;;;;;;;;;;;;;;;
  (ds_if (eq (diana_nodetype_get #$%as_designator) 'dn_entry_id)
	 (progn				  ;elaborate the entry.
	   (let* ((asdes #$%as_designator)
		  (entryq (ct_make_instance 'dt_entry_type
					 'def_occurence asdes))
		  (pair (cons asdes entryq)))
	     (ct_send entryq 'initialize nil)
	     (ct_send #$^thistask 'set_val nil
		      (cons
			pair
			(ct_send #$^thistask 'get_val nil)))))))

#|
		;;;;;;;;;;;;;;;;;;
(def_diana_node dn_subprogram_decl(dead_p)
		;;;;;;;;;;;;;;;;;;
    ;(break in-subprogram-decl)
    (ds_if #$~dead_p 
           (progn
             (ct_send *current_task* 'kill_yourself_and_inferiors)
             (ds_exit)))
    (ds_if #$~starting
	(progn 'compile
               (%= #$~starting nil)	; we found the main procedure!
	       (ds_follow #$%as_designator)))
;	(progn ;(ds_exit)
;	  (ct_send *current_task* 'make_wait_for_inferiors
;		   (ct_send *current_task* 'inferior_tasks))
;	  (break am-I-dead-yet?)
;	  (%= #$~dead_p t)                  ;time to go die.
;	  (ds_follow pc)                  ;by the time I get there I'll be dead.
)
;      (ds_follow #$%as_subprogram_def)
;      (ds_follow #$%as_designator))
|#

		;;;;;;;;;;
(def_diana_node dn_proc_id()
		;;;;;;;;;;

      (ds_call_diana #$%sm_body)
      (ds_return_to_caller))


		;;;;;;;;;;;;;;
(def_diana_node dn_function_id(basetype constraint)
		;;;;;;;;;;;;;;

    (ds_call_diana #$%sm_body)
    (ds_return_to_caller))


		;;;;;;;;;
(def_diana_node dn_return(res evaluatep)
		;;;;;;;;;

    (%= #$~evaluatep t)			; we want to evaluate the result.
    (ds_follow #$%as_exp_void)		; (car #$~res) is the result.stage

    (cond
      (#$~res
       (let* ((result (car #$~res))
	   (rtnobj
	    (let* ((*activation*
		     (get-iv adabe_activation *activation* 'clink))
		   (pc (get-iv adabe_activation *activation* 'pc)))
	      #$~rtnval)))
      (ct_send rtnobj 'set_val nil result))))	  ;perform constraint check.
    (ds_if (not (eq (diana_nodetype_get #$%as_exp_void) 'dn_void))
	   (ds_returnres (car #$~res)))		; return result to caller.stage

    (ds_return_to_caller))


		;;;;;;;;;;;;;;;;;;;;;;;
(def_diana_node dn_predefined_procedure()
		;;;;;;;;;;;;;;;;;;;;;;;

    (funcall #$%ct_lisp_func *activation*))	; call lisp function.


		;;;;;;;;;;;;;;;;;;;;;;
(def_diana_node dn_predefined_function()
		;;;;;;;;;;;;;;;;;;;;;;

    (ds_returnres
      (funcall #$%ct_lisp_func *activation*)))	; call lisp function.


		;;;;;;;;;;;;;;
(def_diana_node dn_constrained(res evaluatep)
		;;;;;;;;;;;;;;

      (%= #$~basetype 
	  (ds_find_type #$%as_name))
      (%= #$~evaluatep t)
      (ds_if #$^constraint
	  (ds_exit)
	  (ds_follow #$%as_constraint)); go find constraints if any
      (ds_if #$^constraint
	  (ds_exit)
	  (progn ;(break in-dn_constrained)
		 (%= #$^constraint #$~res))))


		;;;;;;;;
(def_diana_node dn_stm_s()
		;;;;;;;;


      (ds_follow (first #$%as_list)))


		;;;;;;;;;;;
(def_diana_node dn_null_stm())
		;;;;;;;;;;;

;     (freshline *listing*)
;     (ct_princ "Executing the NULL statement." *listing*)
;     (freshline *listing*))

                ;;;;;;;;;;;;
(def_diana_node dn_named_stm()
                ;;;;;;;;;;;;
    ;;; need to do its as_stm 

   (ds_follow #$%as_id))

		;;;;;;;;;;;;;;;
(def_diana_node dn_named_stm_id()
		;;;;;;;;;;;;;;;

  (ds_call_diana #$%sm_stm))

                ;;;;;;;;;;
(def_diana_node dn_labeled()
                ;;;;;;;;;;
    ;;; need to do its as_stm 
   (ds_follow #$%as_id))

                ;;;;;;;;;;
(def_diana_node dn_label_id()
                ;;;;;;;;;;
    ;;; need to do its as_stm 
   (ds_follow #$%as_stm))

                ;;;;;;;
(def_diana_node dn_goto(labeled process)
                ;;;;;;;
  ;; find the labeled statement.
  (%= #$~labeled (diana_get (diana_get #$%sm_name 'sm_defn) 'ct_labeled))
  ;; ct_change used to be as_name
  (ds_if (null #$~labeled)(lose 'missing-label 'dn_goto))

  ;; find the process for the labeled statement.

    (%= *nuactivation*
	(follow_alink_n_times *activation*
			      (env_depth (diana_get #$~labeled 'as_id))))
  (cond
    ((eq *activation* *nuactivation*)
     (%= *continuation* #$~labeled)
     (%= *nuactivation* nil))
    (t 
     (set-iv adabe_activation *nuactivation* 'pc #$~labeled)))

;  (ct_princ "YOU DESERVE TO LOSE")(ct_terpri)
  
)

		;;;;;;;;
(def_diana_node dn_block (starting mytasks record types formals dscrmts inexc
			  compobj dscrmt_vars del dcls constraint proto)
     		;;;;;;;;
;;;types is used to collect the subtype cxonstraints for types
;;;and the formals for parameters respectively. Each is an A-List indexed
;;;by the defining (dn...id ...) node.
  (%= #$~inexc *exchandler*)
  (%= *exchandler* nil)
  (%= #$~dcls #$%as_item_s)
  (ds_label #$~del)
  (ds_if #$~dcls (ds_call_diana (first #$~dcls)))  ; elaborate the declarations.
  (%= #$~dcls (cdr *_*))
  (ds_if #$~dcls (ds_goto #$~del))
  (ds_call_diana #$%as_stm_s)		  ; execute the statements.
  (%= *exchandler* #$~inexc))

		;;;;;;;
(def_diana_node dn_stub ()
		;;;;;;;
  (ada_raise '|program_error| "missing body"))

		;;;;;;;;;;;;;;;;;
(def_diana_node dn_enum_literal_s()	  ; nothing at runtime.
	        ;;;;;;;;;;;;;;;;;
  (ds_resultis (|attribute_range| pc nil)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Access types

		;;;;;;;;
(def_diana_node dn_access(basetype)
		;;;;;;;;

)

                ;;;;;;;;;;;;        
(def_diana_node dn_allocator(res evaluatep nuobj basetype compobj 
                ;;;;;;;;;;;;
			     basetypespec constraint indexlist nuvars
			     dscrmt_vars dscrmt_constraints dscrmts
			     invar)
  (%= #$~evaluatep t)		;we will evaluate the initializing expression.
  (ds_find_type  (extract_basetype #$%sm_exp_type));find basetype.
 ; (break trace-me)
  (let ((allbt (diana_nodetype_get  #$%as_exp_constrained)))
    (cond ((not (eq allbt 'dn_qualified))
	   (%= #$~basetypespec
	       (ds_find_base_type_spec #$%as_exp_constrained))
	   (%= #$~res nil))
	  (t
	   (%= #$~basetypespec (ds_find_base_type_spec #$%sm_exp_type)))))
;  (break in-disc-alligators1)
  (ds_if (diana_nodep #$~basetypespec)
	 (ds_call_diana #$~basetypespec))	  ;stage
    
    (let ((bts  #$~basetypespec))
      (cond ((is_dscrmt_record bts)	  ;(break frob)
	     (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
	     (%= #$~dscrmt_vars (dscrmt_record%vars bts))
	     (%= bts (dscrmt_record%record *_*))))
      (%= #$~basetypespec bts))
;  (break in-disc-alligators2)
    (%= #$~res nil)			  ;index ranges will be
					  ; collected in res.
    (let ((dc #$~dscrmt_constraints))
      (ds_if dc				  ;collect dscrmts if any.
	     (ds_call_diana dc)))
    (ds_break)				  ;stage
    
    (let ((bts #$~basetypespec))
      (ds_if (diana_nodep bts)
	     (ds_call_diana bts)))
    (ds_break)				  ;stage
    (ds_if (eq  (diana_nodetype_get #$%as_exp_constrained) 'dn_qualified)
	   (ds_call_diana  #$%as_exp_constrained))
;    (break foolowed-constrained)
    (%= #$~indexlist (reverse #$~res))
;  (break in-dn_allocator)
    (ds_find_type #$%sm_exp_type)
    (%= #$~nuobj (ct_make_instance (type_builder #$~basetype)
				'ada_name nil
				'ada_index nil))
    (ct_send #$~nuobj 'initialize
	     `(,#$%sm_exp_type nil ,(setr_builder #$~basetype) ,pc))
;  (ds_call_diana (diana_get #$%as_exp_constrained 'as_constraint))
    (ct_send #$~nuobj 'set_val nil (first #$~res))
;    (break look-at-nuobj)
    (ds_push #$~nuobj #$^res)
;  (break  in-dn_allocator)
    )

                ;;;;;;
(def_diana_node dn_all (res evaluatep name referencep)
		;;;;;;
  (%= #$~referencep t)
  (%= #$~evaluatep nil)
  (ds_follow #$%as_name)		  ;get the access type object.
  (cond ((eq (ct_send  (first #$~name) 'get_val nil)
	     '*null*)
	 (ada_raise '|constraint_error| ".all operation on access null)")))
  (ds_if #$^evaluatep
	 (ds_push (ct_send
		    (ct_send (first #$~name) 'get_val nil)
		    'get_val nil) #$^res)
	 (ds_push (ct_send
		    (first #$~name)
		    'get_val nil) #$^name))	     
)

		;;;;;;;;;;;;;;
(def_diana_node dn_null_access ()
		;;;;;;;;;;;;;;
  (cond (#$~evaluatep
		(ds_push '*null* #$^res))
	 (t (ds_push '*null* #$^name))))

		;;;;;;;;
(def_diana_node dn_array (basetype res basetypespec dscrmt_constraints
				   dscrmt_vars initval indexlist)
		;;;;;;;;
                         

  (ds_call_diana #$%as_dscrt_range_s)	  ;find the index ranges.
  (%= #$^res #$~res)
  (%= #$~res nil)
  (ds_find_type #$%as_constrained)
  (let ((bts (ds_find_base_type_spec #$%as_constrained)))
    (%= #$~initval #$~res)    
    (cond ((is_dscrmt_record bts)
	   (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
	   (%= #$~dscrmt_vars (dscrmt_record%vars bts))
	   (%= bts (dscrmt_record%record *_*))))
    (%= #$~basetypespec bts))
  (%= #$~res nil)			  ;index ranges will be
           				  ; collected in res.
  (let ((dc #$~dscrmt_constraints))
    (ds_if dc				  ;collect dscrmts if any.
	   (ds_call_diana dc)))
  (ds_break);stage

  (%= #$~constraint nil)
  (let ((bts #$~basetypespec))
    (ds_if (diana_nodep bts)  
	   (ds_call_diana bts)))	  ;list=>diana.
  (ds_break);stage
  (%= #$~indexlist #$~res)
  (%= #$^proto (cdr (object_builder nil))))

		;;;;;;;;;;;;;;;;
(def_diana_node dn_dscrt_range_s(res evaluatep constraint rngl rngs rng bts)
		;;;;;;;;;;;;;;;;

  (%= #$~evaluatep t)
  ;;This is a crocko grosso.
  ;;   used to generate a proto for a constrained array. if not invar,
  ;;   we are in a type declaration!
  (ds_if (and #$^invar
	      (eq (diana_nodetype_get (car #$%ct_threadp)) 'dn_constrained))
	 (ds_call_diana (extract_basetype (car #$%ct_threadp))))
  (%= #$~rngs #$%as_list)
  (ds_label #$~rngl)
  (%= #$~rng (ds_pop #$~rngs))
  (%= #$~bts (ds_find_base_type_spec #$~rng))
  (cond ((eq (diana_nodetype_get #$~rng) 'dn_used_name_id)
	 (%= #$~rng (diana_get #$~rng 'sm_defn))))
  (ds_if #$~rng
	 (ds_call_diana (or #$~bts #$~rng)))
  (ds_if #$~rngs (ds_goto #$~rngl))
  (ds_if #$~constraint
	 (%= #$^res #$~constraint)
	 (%= #$^res  #$~res)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Records

		;;;;;;;;;
(def_diana_node dn_record(record basetype name res evaluatep
				 referencep rcs rcl)
		;;;;;;;;;
  ;; First of all make a record object.
  (%= #$~record (ct_make_instance 'dt_record_type
			       'ada_name nil 'ada_index nil
			       'sm_defn nil
			       'current_value (ada_record_value nil)))
  ;; First elaborate the discriminants .. if there are any.
  (let ((dv #$~dscrmt_vars ))
    (ds_if dv (ds_call_diana  dv)))
  (ds_break);stage

  ;; Now enter any specified discriminant constraints.
  (do ((disc
	 (ada_record_value%record (ct_send #$~record 'current_value))(cdr disc))
       (const
	 #$~dscrmts (cdr const)))
      ((or (null const) (null disc)))
    (ct_send (cdar disc) 'set_val nil (car const)))
  ;; Now elaborate the components.
  (%= #$~rcs #$%as_list)
  (ds_label #$~rcl)
  (ds_if #$~rcs   (ds_call_diana (ds_pop #$~rcs )))	  ;stage
  (ds_if #$~rcs (ds_goto #$~rcl))

  ;; Now return the record object as a complex object.
  (%= #$^compobj #$~record))

		;;;;;;;;;;;;;;;
(def_diana_node dn_inner_record(basetype name res evaluatep referencep)
		;;;;;;;;;;;;;;;
  (ds_follow (first #$%as_list))
)

		;;;;;;;;;;;;;;;
(def_diana_node dn_variant_part(dscrmt)
		;;;;;;;;;;;;;;;
  (%= #$~dscrmt
      (ct_send
	(cdr
	  (assq #$%as_name
		(ada_record_value%record
		  (ct_send #$^record 'current_value))))
	'get_val nil))
  (ds_follow #$%as_variant_s))

		;;;;;;;;;;;;
(def_diana_node dn_null_comp ()
		;;;;;;;;;;;;

  )

		;;;;;;;;;;;;
(def_diana_node dn_variant_s(vars varl found)
		;;;;;;;;;;;;
  (%= #$~vars #$%as_list)		  ;list of variants
  (ds_label #$~varl)
  (ds_if (and #$~vars (not #$~found))
	 (ds_call_diana (ds_pop #$~vars)));search for selected variant.
  (ds_if (and #$~vars (not #$~found))
	 (ds_goto #$~varl)))

		;;;;;;;;;;
(def_diana_node dn_variant(chss chsl evaluatep res)
		;;;;;;;;;;
  (%= #$~evaluatep t)			  ;evaluate the choices
  (%= #$~chss #$%as_choice_s)		  ;choices for this variant.
  (ds_label #$~chsl)
  (ds_if #$~chss
	 (ds_call_diana (ds_pop #$~chss)));evaluate this choice.
  (%= #$~found (equal (ds_pop #$~res) #$^dscrmt))
  (ds_if (and #$~chss (not #$~found))
	 (ds_goto #$~chsl))
  (ds_if #$~found
	 ;;if we get here, this variant is the selected one.
	 (ds_follow #$%as_record)))



		;;;;;;;;;;;;;;;;;
(def_diana_node dn_attribute_call(argument res evaluatep name attribute)
                ;;;;;;;;;;;;;;;;;
  
  (%= #$~evaluatep t)
  (ds_if #$%as_exp
	 (ds_call_diana #$%as_exp)); evaluate the argument if present.stage
	 

  (%= #$~argument (ds_pop #$~res));the argument.
  (ds_call_diana #$%as_name);get the object and the attribute name.stage

  (let* ((handler (concat '|attribute_| #$~attribute))
	 (result  (funcall handler (first #$~name) #$~argument)))
    (cond				  ;return result to caller.
      (#$^evaluatep (ds_push result #$^res))
      (t (ds_push result #$^name)))))

		;;;;;;;;;;;;
(def_diana_node dn_attribute(evaluatep referencep)
                ;;;;;;;;;;;;
  
  (%= #$^attribute
      (intern (implode (cadr (diana_get #$%as_id 'lx_symrep)))
	      'user))  ;attribute name.
  (%= #$~referencep t)
  (ds_if #$%as_name (ds_call_diana #$%as_name)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Aggregates.

       ;;;;;;;;;;;;;;;;;;
(defun string_aggregate_p (ag)
       ;;;;;;;;;;;;;;;;;;

  (and (consp ag)(or (eq (car ag) 'lex_string)(eq (car ag) 'lex_char))))


		;;;;;;;;;;;;
(def_diana_node dn_aggregate(res evaluatep shrinking_aggie alp dyna_aggie range)
		;;;;;;;;;;;;

  (%= #$~evaluatep t)			  ;set RHS mode for aggregate eval.
  (cond
    (#$%sm_normalized_comp_s
     (%= #$~shrinking_aggie
	 (cond ((diana_nodep #$%sm_normalized_comp_s)
		(diana_get #$%sm_normalized_comp_s 'as_list))
	       (t (%= #$~dyna_aggie t)
		  #$%sm_normalized_comp_s))))
    (t (%= #$~shrinking_aggie #$%as_list)));++
  (ds_if #$~dyna_aggie
	 (ds_call_diana
	   (let ((range (dynamic_range_rec%range #$~shrinking_aggie)))
	     (cond ((memq (diana_nodetype_get range) '(dn_used_name_id))
		    (diana_get range 'sm_defn))
		   (t range)))))
  (cond ((and #$~dyna_aggie (consp (car #$~res)))
	 (do ((i (coerce_int (caar #$~res)) (1+ i))
	      (val nil (cons (dynamic_range_rec%val #$~shrinking_aggie) val)))
	     ((> i (coerce_int (cadar #$~res)))
	      (%= #$~shrinking_aggie val))))
	(#$~dyna_aggie
	 (%= #$~shrinking_aggie
	     (cons (dynamic_range_rec%val #$~shrinking_aggie) nil))))
  (%= #$~res nil)

  (ds_label #$~alp)			  ;stage

  (ds_if #$~shrinking_aggie
	 (let ((nxt_agponent (ds_pop  #$~shrinking_aggie)))
	   (ds_call_diana nxt_agponent))) ;stage

  (ds_if  #$~shrinking_aggie (ds_goto #$~alp))	  ;stage

;;  (ds_call_diana (first #$%as_list))	  ;evaluate the aggregates exp's,
  (ds_if #$^evaluatep
	 (ds_resultis (nreverse #$~res))
	 (ds_push (nreverse #$~res) #$^name)))	  ;return in the correct order.


		;;;;;;;;
(def_diana_node dn_named()
		;;;;;;;;

  (lose 'be_nanyi 'diana_node_dn_aggregate
	'("Named aggregates are not yet implemented - sorry"))
  )
		;;;;;;;;;;;;;;;;;;;
(def_diana_node dn_dscrmt_aggregate(res evaluatep ds dl)
		;;;;;;;;;;;;;;;;;;;

  (%= #$~evaluatep t)
  (%= #$~ds #$%as_list)
  (ds_label #$~dl)
  (ds_if #$~ds
	 (ds_call_diana (ds_pop #$~ds)))	  ;should be sm_normalized_comp_s
  (ds_if #$~ds (ds_goto #$~dl))
  (%= #$^dscrmts (reverse #$~res))
)
		;;;;;;;;
(def_diana_node dn_fixed(res evaluatep)
		;;;;;;;;

  (%= #$~evaluatep t)
  (ds_follow #$%as_range_void)		  ;get the range.
  (ds_follow #$%as_exp)			  ;get the delta
  (%= #$^res #$~res)			  ;return (delta (L R)) to be used in
					  ;initialize.
)

;; return the range (array declaration)

		;;;;;;;;;;
(def_diana_node dn_integer(res)
		;;;;;;;;;;
  (ds_follow #$%as_range)
  ;(break look-at-range)
  (ds_resultis (car #$~res)))

		;;;;;;;;
(def_diana_node dn_float(res evaluatep)
		;;;;;;;;
  (%= #$~evaluatep t)
  (ds_follow #$%as_range_void)
  (ds_follow #$%as_exp)
  ;(break look-at-range)
  (%= #$^res #$~res);return ( digit (l r))
  )

		 ;;;;;;;;;;
(def_diana_node  dn_type_id()
		 ;;;;;;;;;;
  (ds_resultis (|attribute_range| pc nil )))
  
		 ;;;;;;;;;;;;;
(def_diana_node  dn_subtype_id()
		 ;;;;;;;;;;;;;
  (ds_resultis (|attribute_range| pc nil )))
  

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Object Declarations.


		;;;;;;;;;
(def_diana_node dn_number()
		;;;;;;;;;
)


(def_diana_node dn_dscrmt_var_s()
;  (break ds_var_s-entry)
  (ds_follow (first #$%as_list))
;  (break ds_var_s-exit)
)

		;;;;;;;;;;;
(def_diana_node dn_constant(indexlist basetype nuvars evaluatep res invar
			    ival thistask compobj initval basetypespec
			    constraint elp ids renamep dscrmts
			    dscrmt_constraints dscrmt_vars referencep proto)
		;;;;;;;;;;;
                       
		       
  (%= #$~invar t)
   (%= #$~ids #$%as_id_s)
   (ds_label #$~elp)			  ;stage

   (ds_if #$~ids (ds_call_diana (car #$~ids))) ;stage
   (%= #$~evaluatep t)
   (let ((aod #$%as_object_def))
    (ds_if
      (and aod (eq (diana_nodetype_get aod) 'dn_rename))
      (%= #$~renamep (diana_get aod 'as_name))
      (ds_call_diana aod)))
  (ds_break)
  (let* ((id (car #$~ids))
	 (ts (extract_basetype id)))
    (ds_if (eq (diana_nodetype_get ts) 'dn_task_spec)
	   (progn
	     (%= #$~thistask (ct_make_instance 'dt_task_type
					  'current_value nil
					  'sm_defn ts
					  'def_occurence id))
	     (set-iv adabe_activation *activation* 'locals
		     (cons
		       (cons id #$~thistask )
		       (get-iv adabe_activation *activation* 'locals)	  ; the locals slot.
		       ))
	     (ds_call_diana ts)))
    )
  (ds_break) ;(break look_at-tasks)
   (ds_push #$~res  #$~ival)
   (%= #$~evaluatep nil)
   (ds_pop #$~ids)
   (ds_if #$~ids (ds_goto #$~elp))	  ;stage
   (ds_if (eq (diana_nodetype_get (extract_basetype (car #$%as_id_s)))
	      'dn_task_spec)
	  (ds_exit))

;  (ds_follow (first #$%as_id_s))	  ; build list of identifiers.
;  (ds_follow #$%as_type_spec)	          ; find base type and constraint
  (ds_find_type #$%as_type_spec)
  (%= #$~evaluatep t)			  ; set evaluate mode.
  ; evaluate expression.(init).stage


  (let ((bts (ds_find_base_type_spec #$%as_type_spec)))
        
    (cond ((is_dscrmt_record bts)
	   (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
	   (%= #$~dscrmt_vars (dscrmt_record%vars bts))
	   (%= bts (dscrmt_record%record *_*))))
    ;(break look-at-dscrmt)
    (%= #$~basetypespec bts))
  (%= #$~res nil)			  ;index ranges will be
           				  ; collected in res.
  (let ((dc #$~dscrmt_constraints))
    (ds_if dc				  ;collect dscrmts if any.
	   (ds_call_diana dc)))
  (ds_break);stage

;  (break dn_var)
  (%= #$~constraint nil)
  (let ((bts #$~basetypespec))
    (ds_if (diana_nodep bts)  
	   (ds_call_diana bts)))	  ;list=>diana.
  (ds_break);stage 

  (%= #$~indexlist (or (reverse #$~res) #$~constraint))	  ; find indexlist.(if any)
;      (break in-var)
  ;; Now we have a list of identifiers in nuvar and the basetype in
  ;; basetype. The initialization is in 'res' if it exists.
  ;; All we have to do is create an object of type 'type' for each
  ;; 'nuvar' and put them on the current activation record *activation*
  ;; locals slot. Then if there was an initialization expression, we
  ;; initialize the new object to that value.
  ;; Whats more, if the object is a complex one (currently a record),
  ;; the prototypical object is in compobj.
  ;; Note: In the absence of an initialization *unassigned* will be used
  ;;       to initialize the new object.

;; if we are in the context of a record, we need to insert the record
;; components. Otherwise we need to add these declarations to the
;; current activation record.
  (let ((rec #$^record)
	(newvar #$~nuvars))
    (ds_if rec
	   (%= (ada_record_value%record (ct_send rec 'current_value))
	       (append
		 *_*
		 (mapcar #'(lambda (var)
				      (%= #$~initval (ds_pop #$~ival))
				      (object_builder var))
				  newvar)
		 ;(mapcar #'object_builder newvar);++pmj changed to be the same
		 ;as the non record case 84-3-18
		 ))
	   (let ((*activation*
		   (follow_alink_n_times
		     *activation*
		     (env_depth (car #$%as_id_s)))))
	     (set-iv adabe_activation *activation* 'locals
		     (append
		       (cond
			 (#$~renamep
			  (let ((renamed_var (look_up_ident #$~renamep)))
			    `((,(first #$~nuvars) . ,(cdr renamed_var)))))
			 (t 
			  (mapcar #'(lambda (var)
				      (%= #$~initval (ds_pop #$~ival))
				      (object_builder var))
				  newvar)))
		       (get-iv adabe_activation *activation* 'locals)	  ; the locals slot.
		       )))))
;  (break in-var)
)			  ; returns an A-list of ids and objects.

                ;;;;;;
(def_diana_node dn_var(indexlist basetype nuvars evaluatep res invar ival
		       thistask compobj initval basetypespec constraint elp
		       ids renamep dscrmts dscrmt_constraints dscrmt_vars
		       referencep proto)
		;;;;;;
                       
		       
  (%= #$~invar t)
   (%= #$~ids #$%as_id_s)
   (ds_label #$~elp)			  ;stage

   (ds_if #$~ids (ds_call_diana (car #$~ids))) ;stage
   (%= #$~evaluatep t)
   (let ((aod #$%as_object_def))
    (ds_if
      (and aod (eq (diana_nodetype_get aod) 'dn_rename))
      (%= #$~renamep (diana_get aod 'as_name))
      (ds_call_diana aod)))
  (ds_break)
  (let* ((id (car #$~ids))
	 (ts (extract_basetype id)))
    (ds_if (eq (diana_nodetype_get ts) 'dn_task_spec)
	   (progn
	     (%= #$~thistask (ct_make_instance 'dt_task_type
					  'current_value nil
					  'sm_defn ts
					  'def_occurence id))
	     (set-iv adabe_activation *activation* 'locals
		     (cons
		       (cons id #$~thistask )
		       (get-iv adabe_activation *activation* 'locals)	  ; the locals slot.
		       ))
	     (ds_call_diana ts)))
    )
  (ds_break) ;(break look_at-tasks)
   (ds_push #$~res  #$~ival)
   (%= #$~evaluatep nil)
   (ds_pop #$~ids)
   (ds_if #$~ids (ds_goto #$~elp))	  ;stage
   (ds_if (eq (diana_nodetype_get (extract_basetype (car #$%as_id_s)))
	      'dn_task_spec)
	  (ds_exit))

;  (ds_follow (first #$%as_id_s))	  ; build list of identifiers.
;  (ds_follow #$%as_type_spec)	          ; find base type and constraint
  (ds_find_type #$%as_type_spec)
  (%= #$~evaluatep t)			  ; set evaluate mode.
  ; evaluate expression.(init).stage


  (let ((bts (ds_find_base_type_spec #$%as_type_spec)))
        
    (cond ((is_dscrmt_record bts)
	   (%= #$~dscrmt_constraints (dscrmt_record%dscrmt bts))
	   (%= #$~dscrmt_vars (dscrmt_record%vars bts))
	   (%= bts (dscrmt_record%record *_*))))
    ;(break look-at-dscrmt)
    (%= #$~basetypespec bts))
  (%= #$~res nil)			  ;index ranges will be
           				  ; collected in res.
  (let ((dc #$~dscrmt_constraints))
    (ds_if dc				  ;collect dscrmts if any.
	   (ds_call_diana dc)))
  (ds_break);stage

;  (break dn_var)
  (%= #$~constraint nil)
  (let ((bts #$~basetypespec))
    (ds_if (diana_nodep bts)  
	   (ds_call_diana bts)))	  ;list=>diana.
  (ds_break);stage 

  (%= #$~indexlist (or (reverse #$~res) #$~constraint))	  ; find indexlist.(if any)
;      (break in-var)
  ;; Now we have a list of identifiers in nuvar and the basetype in
  ;; basetype. The initialization is in 'res' if it exists.
  ;; All we have to do is create an object of type 'type' for each
  ;; 'nuvar' and put them on the current activation record *activation*
  ;; locals slot. Then if there was an initialization expression, we
  ;; initialize the new object to that value.
  ;; Whats more, if the object is a complex one (currently a record),
  ;; the prototypical object is in compobj.
  ;; Note: In the absence of an initialization *unassigned* will be used
  ;;       to initialize the new object.

;; if we are in the context of a record, we need to insert the record
;; components. Otherwise we need to add these declarations to the
;; current activation record.
  (let ((rec #$^record)
	(newvar #$~nuvars))
    (ds_if rec
	   (%= (ada_record_value%record (ct_send rec 'current_value))
	       (append
		 *_*
		 (mapcar #'(lambda (var)
				      (%= #$~initval (ds_pop #$~ival))
				      (object_builder var))
				  newvar)
		 ;(mapcar #'object_builder newvar);++pmj changed to be the same
		 ;as the non record case 84-3-18
		 ))
	   (let ((*activation*
		   (follow_alink_n_times
		     *activation*
		     (env_depth (car #$%as_id_s)))))
	     (set-iv adabe_activation *activation* 'locals
		     (append
		       (cond
			 (#$~renamep
			  (let ((renamed_var (look_up_ident #$~renamep)))
			    `((,(first #$~nuvars) . ,(cdr renamed_var)))))
			 (t 
			  (mapcar #'(lambda (var)
				      (%= #$~initval (ds_pop #$~ival))
				      (object_builder var))
				  newvar)))
		       (get-iv adabe_activation *activation* 'locals)	  ; the locals slot.
		       )))))
;  (break in-var)
)

		;;;;;;;;
(def_diana_node dn_slice(res evaluatep referencep name nuarray)
		;;;;;;;;

  (%= #$~referencep t)
  (ds_follow #$%as_name)	;get the array object. => name stage

  (%= #$~evaluatep t)
  (ds_follow #$%as_dscrt_range)	;get the range.        => res stage

  ;;check the bounds of the range.
  (let ((result #$~res)
	(nme #$~name))
    (cond
      ((eq (and (consp (first nme))(first (first nme))) 'lex_string));temp crock+++
      ((> (first (first result))(second (first result)))) ;null slice. -- OK
      ((> (second (first result))
	  (second (first (ct_send (first nme) 'index_list))))
       (ada_raise '|constraint_error| "slice out of bounds"))
      ((< (first (first result))
	  (first (first (ct_send (first nme) 'index_list))))
       (ada_raise '|constraint_error| "slice out of bounds")))
    (%= #$~nuarray			  ;make an array object.
	(let ((arobj (first nme)))
	  (cond ((instancep arobj)
		 (ct_make_instance 'dt_array_type
			 'sm_defn nil	  ;(ct_send arobj 'sm_defn)
			 'index_list result	  ;the new range.
			 'multipliers (ct_send arobj 'multipliers)
			 'starters (ct_send  arobj 'starters)
			 'ada_name (ct_send  arobj 'ada_name)
			 'ada_index nil
			 'array_storage
			 (ct_send arobj 'array_storage)
			 ))
		((and (consp arobj);;total crock, do right later.+++
		      (eq (car arobj) 'lex_string))
		 (do ((oldstr (nthcdr (1- (caar result)) (cadr arobj))
			      (cdr oldstr) )
		      (newstr nil)
		      (i (caar result) (1+ i)))
		     ((> i (cadar result)) 
		      (list 'lex_string (nreverse newstr)))
		   (ct_push (car oldstr) newstr)))
		      )))
    (cond				  ;Make new slice available for use.
      (#$^evaluatep (ds_push #$~nuarray #$^res))
      (t            (ds_push #$~nuarray #$^name))))
;  (break in-slice)
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Expressions / object access.


		;;;;;;;;;
(def_diana_node dn_var_id()
		;;;;;;;;;

;    (ds_push #$%lx_symrep #$^nuvars)	;sideffect dn_var's list.
    (ds_push #$%sm_defn #$^nuvars))	;sideffect dn_var's list.


		;;;;;;;;;;
(def_diana_node dn_comp_id()
		;;;;;;;;;;

;    (ds_push #$%lx_symrep #$^nuvars)	;sideffect dn_var's list.
    (ds_push #$%sm_defn #$^nuvars))	;sideffect dn_var's list.

		;;;;;;;;;;
(def_diana_node dn_dscrmt_id()
		;;;;;;;;;;

;    (ds_push #$%lx_symrep #$^nuvars)	;sideffect dn_var's list.
    (ds_push #$%sm_defn #$^nuvars))	;sideffect dn_var's list.


		;;;;;;;;;;
(def_diana_node dn_enum_id()
		;;;;;;;;;;

;    (ds_push #$%lx_symrep #$^nuvars)	;sideffect dn_var's list.
    (ds_push #$%sm_defn #$^nuvars))	;sideffect dn_var's list.


		;;;;;;;;;;;;
(def_diana_node dn_number_id()
		;;;;;;;;;;;;

;    (ds_push #$%lx_symrep #$^nuvars)	;sideffect dn_var's list.
    (ds_push #$%sm_defn #$^nuvars))	;sideffect dn_var's list.


		;;;;;;;;;;;
#|(def_diana_node dn_const_id()
		;;;;;;;;;;;
  (ds_if #$%sm_obj_def
	 (ds_call_diana #$%sm_obj_def)
	 (ds_call_diana #$%sm_init_exp)))|#

		;;;;;;;;;
(def_diana_node dn_const_id()
		;;;;;;;;;

;    (ds_push #$%lx_symrep #$^nuvars)	;sideffect dn_var's list.
    (ds_push #$%sm_defn #$^nuvars))	;sideffect dn_var's list.



		;;;;;;;;;;;;;;;;;;
(def_diana_node dn_character_literal()  	; side effect callers #$~res
		;;;;;;;;;;;;;;;;;;

  (cond
    (#$~evaluatep
     (ds_push (convert_integer_to_char (caadr #$%lx_symrep)) #$~res))
    (#$~referencep
     (ds_push (convert_integer_to_char (caadr #$%lx_symrep)) #$~name))
    (t (lose 'be_wmawi 'diana_node_dn_character_literal
	     ()
	     '("what mode are we in ? dn_character_literal")))))

		;;;;;;;;;;;;;;;;;;
(def_diana_node dn_numeric_literal()  	; side effect callers #$~res
		;;;;;;;;;;;;;;;;;;

  (cond
    (#$~evaluatep (ds_push (numval #$%lx_numrep) #$~res) )
    (#$~referencep (ds_push (numval #$%lx_numrep) #$~name))
    (t (lose 'be_wmawi 'diana_node_dn_numeric_literal
	     ()
	     '("what mode are we in ? dn_numeric_literal")))))
;    (ds_push (numval #$%lx_numrep) #$~res)) 


		;;;;;;;;;;;;;;;;;
(def_diana_node dn_string_literal()   	; put string onto callers #$~res
		;;;;;;;;;;;;;;;;;

  (cond
    (#$~evaluatep (ds_push #$%lx_symrep #$~res))
    (#$~referencep (ds_push #$%lx_symrep #$~name))
    (t (lose 'be_wmami 'diana_node_dn_string_literal
	     ()
	     '("what mode are we in ? dn_string_literal")))))

;;; There are three modes in which used_name_id's can be used.
;;; (1) RHS mode, evaluatep = t
;;;     returns the value of the id.
;;; (2) LHS mode, referencep = t
;;;     returns the object that id is bound to (used primarily in assignment).
;;; (3) NAME mode,
;;;     returns the id itself, used primarily in declarations.

		;;;;;;;;;;;;;;;
(def_diana_node dn_used_name_id()
		;;;;;;;;;;;;;;;
 (let* ((smdef (diana_get pc 'sm_defn))
	(ntype (diana_nodetype_get smdef)))
   (cond
     (#$~evaluatep			  ; are we evaluating names? RHS mode?
      (cond
	((memq ntype
	       '(dn_enum_id dn_type_id dn_subtype_id dn_def_char))
	 (ds_push smdef #$~res)) 
	((eq ntype 'dn_number_id)
	 (ds_push (be_static_eval pc) #$~res))
	((eq ntype 'dn_dscrmt_id)
	 (ds_push (ct_send
		    (ct_send #$~record 'get_val #$%sm_defn)
		    'get_val
		    nil)
		  #$~res))
	#|((eq ntype 'dn_const_id)
	 (ds_call_diana #$%sm_defn))|#  
	(t (ds_push (ds_valof pc) #$~res))))	  ; record of pc.
     (#$~referencep			  ; is this LHS mode?
      (cond
	((memq ntype
	       '(dn_enum_id dn_type_id dn_subtype_id dn_predefined_type dn_def_char))
	 (ds_push smdef #$~name))
	((eq ntype 'dn_number_id)
	 (ds_push (be_static_eval pc) #$~name))
	#|((eq ntype 'dn_const_id)
	 (ds_call_diana #$%sm_defn))|#  
	(t 
	 (ds_push
	   (cdr (look_up_ident pc))	  ;object to which pc is bound.
	   #$~name))))
     (t  (ds_push pc #$~name)))))	  ; otherwise return the name.

       ;;;;;;;;;;;;;;;;;;;;;
(defun conversion_compatible (val type)
       ;;;;;;;;;;;;;;;;;;;;;
  ;;this is not finished it needs to ensure that
  ;;this value is compatible with the type.
  ;; For the moment just return t
  (let* ((typid (or (and (eq (diana_nodetype_get type) 'dn_selected)
			 (diana_get
			   (diana_get type 'as_designator_char)
			   'sm_defn))
		    (diana_get type 'sm_defn)))
	 (typspec (and typid (diana_get typid 'sm_type_spec)))
	 (range (and typspec
		     (ct_selectq
		       (diana_nodetype_get typspec)
		       ((dn_float dn_fixed)
			(let*
			  ((r (diana_get typspec 'as_range_void))
			   (lb
			     (cond ((eq (diana_nodetype_get r)
					'dn_void)
				    *float_first*)
				   (t
				    (static_eval (diana_get r 'as_exp1)))))
			   (ub
			     (cond ((eq (diana_nodetype_get r)
					'dn_void)
				    *float_last*)
				   (t (static_eval (diana_get r 'as_exp2))))))
			  (list lb ub)))
		       (dn_derived
			 nil)
		       (otherwise
			 (let ((rang (|attribute_range| typid nil)))
			   (cond ((consp (first rang))
				  `(,(fpv_to_real_conversion (car rang))
				    ,(fpv_to_real_conversion (cadr rang))))
				 (t rang))))))))
    (cond ((numberp val)
	   (cond ((and range
		       (equal (car range) nil))
		  t)
		 ((and range
		       (or (= val (first range))
			   (> val (first range)))
		       (or (= val (second range))
			   (< val (second range))))
		  t)
		 
		 ((and range
		       (or (< val (first range))
			   (> val (second range))))			 
		  (ada_raise '|constraint_error|
			     "number out of range in conversion"))
		 (t t)))
	  (t   t))))
  
                ;;;;;;;;;;;;;
(def_diana_node dn_conversion()
                ;;;;;;;;;;;;;
  ;;; There needs to be a check that the return value of the conversion 
  ;;; is assignment compatible with the conversion type.
  (ds_call_diana #$%as_exp)
  (cond (#$^evaluatep (conversion_compatible (car #$^res) #$%as_name))
	((instancep (car #$^name))
	 (conversion_compatible (ct_send (car #$^name) 'get_val nil) #$%as_name))
	(t (conversion_compatible (car #$^name) #$%as_name))))

                ;;;;;;;;;;;;
(def_diana_node dn_qualified()
                ;;;;;;;;;;;;

  (ds_call_diana #$%as_exp))

		;;;;;;;;
(def_diana_node dn_index ()
		;;;;;;;;
  )

		;;;;;;;;;;
(def_diana_node dn_indexed(res name referencep evaluatep arrobj indexed)
		;;;;;;;;;;

  (%= #$~referencep t)
  (ds_follow #$%as_name)		  ; get the array object.stage
  (%= #$~arrobj (first #$~name))	  ; => arrobj
  (%= #$~evaluatep t)
  (%= #$~res nil)
  (ds_follow #$%as_exp_s)	  ; evaluate the indices.stage

  (%= #$~indexed (ct_send #$~arrobj 'get_val (reverse #$~res)))	  ; get object.
  (cond
    (#$^evaluatep			  ; mom in RHS mode?
     (ds_resultis (ct_send #$~indexed 'get_val nil)))
    (#$^referencep
     (ds_push #$~indexed #$^name))
    (t (lose 'be_wmawi 'diana_node_dn_indexed
	     ()
	     '("in dn_indexed ... not in LHS or RHS mode!!")) ))
  )
    
;;; selected needs to be hacked to work for  packages, tasks, 
;;; functions and procedures too.

		;;;;;;;;;;;
(def_diana_node dn_selected  (name res referencep evaluatep recobj selected)
		;;;;;;;;;;;

  (%= #$~referencep t)
  (ds_if (or
	   (memq (diana_nodetype_get #$%as_name) '(dn_selected dn_indexed dn_all))
	   (and (eq (diana_nodetype_get #$%as_name) 'dn_used_name_id)
		(memq (diana_nodetype_get
			(diana_get #$%as_name 'sm_defn))
		      '(dn_in_id dn_out_id dn_in_out_id dn_var_id))))
	 (ds_follow #$%as_name))		  ; get the record object.stage

  (cond ((not #$^evaluatep) (%= #$~referencep #$^referencep)))
  (%= #$~evaluatep #$^evaluatep)
  (%= #$~recobj (first #$~name))	  ; => recobj
;  (break in-dn_selected)
  (ds_if (or (null #$~recobj)
	     (and
	       (eq (diana_nodetype_get #$%as_name) 'dn_used_name_id)
	       (memq (diana_nodetype_get (diana_get #$%as_name 'sm_defn))
		     '(dn_package_id dn_proc_id dn_function_id dn_task_body_id))))
	 (progn
	   (ds_follow #$%as_designator_char )
	   )
	 (%= #$~selected
	     (ct_send #$~recobj 'get_val
		      (diana_get #$%as_designator_char 'sm_defn))))	  ;stage

;  (break look-at-selected)
  (ds_if (or (null #$~recobj)
	     (and
	       (eq (diana_nodetype_get #$%as_name) 'dn_used_name_id)
	       (memq (diana_nodetype_get (diana_get #$%as_name 'sm_defn))
		     '(dn_package_id dn_proc_id dn_function_id dn_task_body_id))))
	 (cond
	   (#$^evaluatep	    
	    (ds_resultis (first #$~res)))
	   (#$^referencep	    
	    (ds_push (first #$~name) #$^name)))
	 (cond
	   (#$^evaluatep		  ; mom in RHS mode?
	    (ds_resultis (ct_send #$~selected 'get_val nil)))
	   (#$^referencep
	    (ds_push #$~selected #$^name))
	   (t (lose 'be_wmawi 'diana_node_dn_selected
		    ()
		    '("in dn_selected ... not in LHS or RHS mode!!")) )))
;  (break in-dn_selected)
  )
      
    
;;; used in array indices. simply evaluate the list of expressions.
;;; note, the resulting list of values will be in the reverse order
;;; upon completion. (in callers #$~res) and must be reversed before
;;; used. Also used in normalized parameters.. same applies.

		;;;;;;;;
(def_diana_node dn_exp_s()
		;;;;;;;;

    (ds_follow (first #$%as_list)))


		;;;;;;;;;;;;;;;;;;
(def_diana_node dn_predefined_type())
		;;;;;;;;;;;;;;;;;;


		;;;;;;;;;;;;;;;;
(def_diana_node dn_param_assoc_s()
		;;;;;;;;;;;;;;;;

  (ds_follow (first #$%as_list)))


		;;;;;;;;;;;;;
(def_diana_node dn_membership(res evaluatep referencep not_in_p resp)
		;;;;;;;;;;;;;

  (%= #$~evaluatep t)
  (ds_call_diana (find_range #$%as_type_range))	  ;find the range => res stage

  (ds_follow #$%as_exp)			  ;find the expression. stage

  (%= #$~not_in_p (eq (diana_nodetype_get #$%as_membership_op) 'dn_not_in))
  (let ((result #$~res))
    (%= #$~resp (and (ge (coerce_int (first result))
			 (coerce_int (first (second result))))
		     (le (coerce_int (first result))
			 (coerce_int (second (second result)))))))
  (cond (#$~not_in_p (%= #$~resp (not #$~resp))))
  (cond
    (#$^evaluatep
     (ds_push (cond (#$~resp *ct_ada_true*)(t *ct_ada_false*)) #$^res))
    (t
     (ds_push (cond (#$~resp *ct_ada_true*)(t *ct_ada_false*)) #$^name))))
    

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Miscellaneous statements.


		;;;;;;;;;
(def_diana_node dn_assign(name res evaluatep referencep)
		;;;;;;;;;

  (%= #$~evaluatep t)			  ; we will evaluate names in the RHS
  (ds_call_diana #$%as_exp)			  ; evaluate the R.H.S.
  (%= #$~evaluatep nil)			  ; don't evaluate LHS.
  (%= #$~referencep t)			  ; but return a reference.
  (ds_call_diana #$%as_name)		  ; evaluate    L.H.S.
;  (break frob)
  (ct_send (first #$~name) 'set_val nil (first #$~res))
					  ; update the value associated with #$~name
  )

		;;;;;;;;;
(def_diana_node dn_pragma(params name evaluatep referencep ppl
		;;;;;;;;;

				 evp pragmads res pragmaname)
					  ; runtime semantics for a pragma (if any).
  (%= #$~pragmaname (intern (implode (cadr #$%as_id))
			    'user))
  (cond
    ((get #$~pragmaname 'lhs_params)
     (%= #$~referencep t))		  ;find the addresses of the parameters.
    (t
     (%= #$~evaluatep t)))		  ; lets evaluate the parameters.
  (%= #$~name nil)
  (%= #$~res nil)
  (%= #$~params nil)
#|
  (ds_if (second (diana_get #$%as_param_assoc_s 'as_list))
	 (ds_call_diana (second (diana_get #$%as_param_assoc_s 'as_list))); onto params
	 )
|#
  (%= #$~ppl (cdr (diana_get #$%as_param_assoc_s 'as_list)))
  (ds_label #$~evp)			  ;loop on eval parameters. stage

  (ds_if #$~ppl				  ;if there are parameters.
	 (ds_call_diana (first #$~ppl)))  ;evaluate the first. stage

  (ds_if #$~ppl (%= #$~ppl (cdr #$~ppl))) ;cdr down the parameter liust stage

  (ds_if #$~ppl (ds_goto #$~evp))	  ;stage

  (%= #$~params
      (cons
	(first (diana_get #$%as_param_assoc_s 'as_list))
	(reverse (cond (#$~referencep #$~name)(t #$~res)))))
					  ; get parameters into the right order.
  (%= #$~pragmads (get #$~pragmaname 'pragma_runtime_semantics))
;  (break in-dn_pragma)
  (cond 
    ((null #$~pragmads)
     (lose 'be_mrsp 'diana_node_dn_pragma
	   ()
	   '("Missing runtime semantics for PRAGMA")))
    (t (funcall #$~pragmads #$~params )))); run the ds over the parameters.


;;; This diana node is created to implement the pragma interface(lisp ..).



		;;;;;;;;;;;;;;
(def_diana_node dn_ct_lispcall() ; pass control to lisp function.
		;;;;;;;;;;;;;;

    (funcall #$%ct_function *activation*))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; These nodes do nothing at all at runtime.


		;;;;;;;
(def_diana_node dn_void ()
		;;;;;;;

)


		;;;;;;
(def_diana_node dn_use ()
		;;;;;;

)

		;;;;;;;;;;;;;
(def_diana_node dn_simple_rep ())
		;;;;;;;;;;;;;

		;;;;;;;;;;;;;
(def_diana_node dn_record_rep ())
		;;;;;;;;;;;;;


		 ;;;;;;;
;(def_diana_node dn_void ())
		 ;;;;;;;

;;; Define the runtime semantics of a lisp_call pragma.
(defprop |lisp_call|
    (lambda(params)
	(funcall 
	    (intern (implode (cadr (diana_get (first params) 'lx_symrep)))
		    'user)
	    (cdr params)))
    pragma_runtime_semantics)

;;; Define the runtime semantics of a list pragma.
(defprop |list|
    (lambda(params) nil)
    pragma_runtime_semantics)

(defprop |page|
    (lambda(params) nil)
    pragma_runtime_semantics)

(defprop |pack|
    (lambda(params) nil)
    pragma_runtime_semantics)

;;; Define the runtime semantics of a annotate pragma.
(defprop |annotate|
    (lambda(params)
	(apply 
	    (intern (implode (cadr (diana_get (first params) 'lx_symrep)))
		    'user)
	    (massage_annotation_parameters (cdr params))))
    pragma_runtime_semantics)

(defprop |annotate| t lhs_params) ;takes reference parameters!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Internal Use Only Functions/Macros -- 
       ;;;;;
(defun mapop(opname)
       ;;;;;

  (ct_selectq opname
	      (unary_not 'ct_ada_not)	  ; not operator.
	      (unary_minus 'minus)	  ; negation.
	      (unary_plus 'plus)	  ; unary addition
	      (ampersand #'ct_ada_string_concat)
	      (star 'times)		  ; multiply operator.
	      (plus 'plus)		  ; addition operator.
	      (minus 'difference)
	      (slash 'quotient)		  ; division.
	      (and   'ct_ada_and)	  ;logical AND.
	      (or    'ct_ada_or)	  ;logical OR.
	      (equals 'ct_ada_equal)
	      (lt 'ct_ada_lessp)
	      (gt 'ct_ada_greaterp)
	      (ge 'ct_ada_ge)
	      (le 'ct_ada_le)
	      (notequals #'(lambda(n m)(ct_ada_not (ct_ada_equal n m))))
	      (mod #'(lambda(n m)
		       (let ((rem (remainder n m)))
			 (cond
			   ((or (and (minusp n)(not (minusp m)))
				(and (minusp m)(not (minusp n))))
			    (difference m rem))
			   (t rem)))))
	      (abs 'abs)
	      (starstar #'(lambda(m n)
			    (do ((ct n (1- ct))
				 (pr 1 (* pr m)))
				((zerop ct) pr))))
	      (rem 'remainder)
	      (t (lose 'be_bionyi 'mapop
		       `("Built in function ~A not yet implemented" opname)
		       ()))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Functions on Ada string objects.
       ;;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_equal(str1 str2)
       ;;;;;;;;;;;;;;;;;;;

  (cond ((equal str1 str2) *ct_ada_true*)))

       ;;;;;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_notequal(str1 str2)
       ;;;;;;;;;;;;;;;;;;;;;;

  (cond ((equal str1 str2) *ct_ada_false*)))

       ;;;;;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_greaterp(str1 str2)
       ;;;;;;;;;;;;;;;;;;;;;;

  (cond
    ((> (first str1)(first str2)) *ct_ada_true*)
    ((< (first str1)(first str2)) *ct_ada_false*)
    ((and (cdr str1)(cdr str2)) (ct_ada_string_greaterp (cdr str1)(cdr str2)))
    ((cdr str1) *ct_ada_true*)
    ((cdr str2) *ct_ada_false*)
    (t (lose 'bif_strgr 'ct_ada_string_greaterp () "holly shit"))))

       ;;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_lessp(str1 str2)
       ;;;;;;;;;;;;;;;;;;;

  (cond
    ((< (first str1)(first str2)) *ct_ada_true*)
    ((> (first str1)(first str2)) *ct_ada_false*)
    ((and (cdr str1)(cdr str2)) (ct_ada_string_lessp (cdr str1)(cdr str2)))
    ((cdr str1) *ct_ada_false*)
    ((cdr str2) *ct_ada_true*)
    (t (lose 'bif_strls 'ct_ada_string_lessp () "holly shit"))))

       ;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_ge_p(str1 str2)
       ;;;;;;;;;;;;;;;;;;

  (cond

    ((equal str1 str2) *ct_ada_true*)
    ((> (first str1)(first str2)) *ct_ada_true*)
    ((< (first str1)(first str2)) *ct_ada_false*)
    ((and (cdr str1)(cdr str2)) (ct_ada_string_greaterp (cdr str1)(cdr str2)))
    ((cdr str1) *ct_ada_true*)
    ((cdr str2) *ct_ada_false*)
    (t (lose 'bif_strgr 'ct_ada_string_greaterp () "holly shit"))))

       ;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_le_p(str1 str2)
       ;;;;;;;;;;;;;;;;;;

  (cond
    ((equal str1 str2) *ct_ada_true*)
    ((< (first str1)(first str2)) *ct_ada_true*)
    ((> (first str1)(first str2)) *ct_ada_false*)
    ((and (cdr str1)(cdr str2)) (ct_ada_string_lessp (cdr str1)(cdr str2)))
    ((cdr str1) *ct_ada_false*)
    ((cdr str2) *ct_ada_true*)
    (t (lose 'bif_strls 'ct_ada_string_lessp () "holly shit"))))

       ;;;;;;;;;;;;;;;;;;;;
(defun ct_ada_string_concat(str1 str2)
       ;;;;;;;;;;;;;;;;;;;;

  (cond
    ((and (ada_string_or_char str1) (ada_string_or_char str2))
     `(lex_string ,(append (second str1)(second str2))))
    (t (lose 'be_naas 'ct_ada_string_concat
	     ()
	     '("Not an Ada string")))))

       ;;;;;;;;;;;;;;;;;;
(defun ada_string_or_char(s)
       ;;;;;;;;;;;;;;;;;;

  (memq (car s) '(lex_string lex_char)))

       ;;;;;;;;;;
(defun ct_ada_and(tv1 tv2)
       ;;;;;;;;;;

  (cond
    ((and (eq tv1 *ct_ada_true*)(eq tv2 *ct_ada_true*)) *ct_ada_true*)
    (t *ct_ada_false*)))

       ;;;;;;;;;
(defun ct_ada_or(tv1 tv2)
       ;;;;;;;;;

  (cond
    ((or  (eq tv1 *ct_ada_true*)(eq tv2 *ct_ada_true*)) *ct_ada_true*)
    (t *ct_ada_false*)))

       ;;;;;;;;;;
(defun ct_ada_not(atv)
       ;;;;;;;;;;

  (cond
    ((eq atv *ct_ada_true*) *ct_ada_false*)
    ((eq atv *ct_ada_false*) *ct_ada_true*)
    (t (lose 'be_naatv 'ct_ada_not
	     ()
	     '("Not an Ada truth value")))))

#|
       ;;;;;;;;;;;;
(defun ct_ada_equal(avn avm)
       ;;;;;;;;;;;;

  (cond
    ((ada_string_or_char avn)
     (ct_ada_string_equal avn avm))
    (t
     (cond
       ((equal avn avm) *ct_ada_true*)
       (t              *ct_ada_false*)))))
|#

       ;;;;;;;;;;;;
(defun ct_ada_equal(avn avm)
       ;;;;;;;;;;;;

  (cond
    ((equal avn avm) *ct_ada_true*)
    (t              *ct_ada_false*)))

       ;;;;;;;;;;;;
(defun ct_ada_lessp(avn avm)
       ;;;;;;;;;;;;

  (cond
    ((lessp avn avm) *ct_ada_true*)
    (t              *ct_ada_false*)))

       ;;;;;;;;;;;;;;;
(defun ct_ada_greaterp(avn avm)
       ;;;;;;;;;;;;;;;

  (cond
    ((greaterp avn avm) *ct_ada_true*)
    (t              *ct_ada_false*)))

       ;;;;;;;;;
(defun ct_ada_le(avn avm)
       ;;;;;;;;;

  (cond
    ((greaterp avn avm) *ct_ada_false*)
    (t                   *ct_ada_true*)))

       ;;;;;;;;;
(defun ct_ada_ge(avn avm)
       ;;;;;;;;;

  (cond
    ((lessp avn avm) *ct_ada_false*)
    (t                *ct_ada_true*)))


       ;;;;;;;;;;;;;;
(defun object_builder(id)
       ;;;;;;;;;;;;;;

  (let ((nuobj `(,id . ,(ct_make_instance (type_builder #$~basetype)
				       'ada_name nil
				       'ada_index nil)))
	(setter    (setr_builder #$~basetype)))
    (cond ((eq (type_builder #$~basetype) 'dt_fixed_point_type)
	   (cond ((null (second #$~indexlist)); delta not specified for subtype
		  (%= #$~indexlist
		      (list (first *_*)
			    (extract_delta_from_fixed_pt_subtype id))))))
	  ((eq (type_builder #$~basetype) 'dt_floating_type)
	   ;(break look-at-indexlist)
	   (cond ((null (second #$~indexlist));range or digits not specified
		  (cond ((null (consp (first #$~indexlist)));range not there
			 ;(break look-at-indexlist)
			 (%= #$~indexlist
			     (list (list *float_first* *float_last*)
				   (first *_*)))))))))
	  
    (ct_send
      (cdr nuobj)
      'initialize 
      `(,(cond
	   ((not (diana_node_accepts_attributep pc 'as_type_spec))
	    (diana_get pc 'as_constrained))
	   ((eq (diana_nodetype_get (extract_basetype #$%as_type_spec)) 'dn_array)
	    #$%as_type_spec)
	   (t
	    (let ((asnam
		(diana_get #$%as_type_spec 'as_name)))
	      (cond ((diana_node_accepts_attributep asnam 'sm_defn)
		     (diana_get asnam 'sm_defn))
		    ((diana_node_accepts_attributep asnam 'as_designator_char)
		     (diana_get asnam 'as_designator_char))))))
	,#$~indexlist			          ;the path
	,setter				  	;the initialization fn.
	,id))				  ;the id itself.
    (ct_send (cdr nuobj)
		 'set-ada_name
		 (and id (intern (implode (cadr (diana_get id 'lx_symrep)))
				 'user)))
    (cond
      (#$~initval				  ; was there an init?
       (ct_send
	 (cdr nuobj)
	 'set_val nil (car #$~initval))))	  ;generalize++
    nuobj)
  )

	;;;;;;;;;;;;
;(defun path_builder(ts)		; return an index list.
	;;;;;;;;;;;;

;  '((1 10)));++

       ;;;;;;;;;;;;
(defun setr_builder(ts)		; return an initializing function.
       ;;;;;;;;;;;;

  (ct_selectq ts
	      (|integer| #'unassignedf)
	      (|access| #'unassignedf)
	      (|task| #'unassignedf)
	      (|float| #'unassignedf)
	      (|fixed| #'unassignedf)
	      (|**any_type**| #'unassignedf)
	      (|**any_fixed**| #'unassignedf)
	      (|**any_integer**| #'unassignedf)
	      (|**any_float**| #'unassignedf)
	      (|**any_real**| #'unassignedf)
	      (|enumeration| #'unassignedf)
	      (|array| #'intobjmake)	
	      (|record| #'recobjmake)
	      (fixed  #'unassignedf)
	      (record   #'recobjmake) 
	      (array   #'intobjmake)
	      (integer #'unassignedf)
	      (access #'unassignedf)
	      (task #'unassignedf)
	      (float #'unassignedf)
	      (enumeration #'unassignedf)
	      (otherwise (lose 'be_ttnyi 'setr_builder
			       ()
			       '("this type not yet implemented ~A" ts)))))

       ;;;;;;;;;;
(defun recobjmake(i)
       ;;;;;;;;;;

;    (break in-recobjmake)
    (ct_send (ct_send #$~compobj 'copyself) 'current_value))
       ;;;;;;;;;;
(defun intobjmake(i)
       ;;;;;;;;;;

;    (break in-intobjmake)
    (ct_send #$~proto 'copyself))

       ;;;;;;;;;;;
(defun unassignedf(i)
       ;;;;;;;;;;;

  '*unassigned*)

       ;;;;;;;;;;;;
(defun intbuildtemp(i)
       ;;;;;;;;;;;;

  (let ((intobj (ct_make_instance 'dt_integer_type
			       'ada_name nil
			       'ada_index nil)))
    (ct_send intobj 'initialize '(nil nil #'unassignedf nil))
    intobj))

       ;;;;;;;;;;;;
(defun type_builder(ts)		; return a builder for the typespec.
       ;;;;;;;;;;;;

  (ct_selectq ts
	      (integer 'dt_integer_type)
	      (|integer| 'dt_integer_type);simple hack to overcome case problems on
	      (enumeration 'dt_enumeration_type)  ;the LM, preobably can delete all non
	      (|enumeration| 'dt_enumeration_type);quoted lines (to be done)++
	      (string 'dt_string_type)
	      (|string| 'dt_string_type)
	      (float 'dt_floating_type)
	      (|float| 'dt_floating_type)
	      (fixed 'dt_fixed_point_type)
	      (|fixed| 'dt_fixed_point_type)
	      (|**any_real**| 'dt_floating_type)
	      (|**any_fixed**| 'dt_fixed_point_type)
	      (|**any_type**| 'dt_integer_type) ;;this is going to cause problems
	      (|**any_integer**| 'dt_integer_type)
	      (|**any_float**| 'dt_floating_type)
	      (access 'dt_access_type)
	      (|access| 'dt_access_type)
	      (task 'dt_task_type)
	      (|task| 'dt_task_type)
	      (array 'dt_array_type)
	      (|array| 'dt_array_type)
	      (record 'dt_record_type)
	      (|record| 'dt_record_type)
	      (otherwise (lose 'be_ttnyi 'type_builder
			       ()
			       '("this type not yet implemented")))))

       ;;;;;;
(defun numval(adanumconst)	; xlate lexical number into a lisp number.
       ;;;;;;
  
  (cond
    ((is_la_num adanumconst)
     (let ((res
	     (errset
	       (let ((wholepart (la_num%wholepart adanumconst))
		     (fractpart (la_num%fractpart adanumconst))
		     (base (la_num%base adanumconst))
		     (floatp (la_num%floatp adanumconst))
		     (exponent  (la_num%exp       adanumconst))
		     (fdigs (la_num%fdigs adanumconst)))
		 (cond (floatp
			(times (plus wholepart
				     (convert_fract base fractpart fdigs))
			       (expt (float base) exponent)))
		       (t (times wholepart (expt base exponent)))))
	       nil)))
       (cond (res (car res))
	     (t
	      (cond
		(*infrontend*
		 (la_gripe '("This numeric literal cannot be interpreted.")
		     '((lrmref "LRM" (lrmsec 2 4 nil) (lrmpar 2 nil))))
		 (cond ((la_num%floatp adanumconst) 1.0)
		      (t 1)))
		(t
		 (ct_format *userout*
			    "Lexical error:~%~
			     This numeric literal cannot be interpreted.~%~
			     Reference: LRM Section 2.4, Paragraph 2")
		 (*throw 'cant_continue 'cant_continue)))))))
    (t (lose 'be_nan 'numval
	     ()
	     '("~A is not a number" adanumconst)))))

       ;;;;;;;;;;;;;
(defun convert_fract (base fract fdigs)
       ;;;;;;;;;;;;;
  (let* ((*nopoint t))
    (quotient (float fract) (expt base fdigs))))

;;; eof
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; temporary IO. to be commented out to serve as an example.
;;;
;;;	;;;;;;;;
;;;(defun |lnewline|(ar)
;;;	;;;;;;;;
;;;
;;;  (do ((i 1 (1+ i)))
;;;      ((greaterp i (ct_send
;;;		     (cdr
;;;		       (assoc
;;;			 `(lex_ident ,(uplowlist (exploden 'spacing)))
;;;			 (ct_send ar 'locals)))
;;;		     'get_val nil)))
;;;    (ct_terpri *userout*)))
;;;
;;;	;;;;;;;
;;;(defun |lgetint|(ar)
;;;	;;;;;;;
;;;
;;;    (let ((intadr (cdr
;;;		      (assoc
;;;			  `(lex_ident ,(uplowlist (exploden 'item)))
;;;			  (ct_send ar 'locals)))))
;;;	(ct_send intadr 'set_val nil (read_integer *userin*))))
;;;
;;;#|
;;;       ;;;;;;;;;;;
;;;(defun read_robust(strm)
;;;       ;;;;;;;;;;;
;;;
;;;  (let ((val (errset (ct_read strm) nil)))
;;;    (or val (read_robust strm))))
;;;
;;;       ;;;;;;;;;;;;
;;;(defun read_integer(st)
;;;       ;;;;;;;;;;;;
;;;
;;;    (let ((inp (do ((num 0)
;;;		    (dig (- (ct_tyi st) #/0)(- (ct_tyi st) #/0)))
;;;		   ((or (> dig 9)(< dig 0))
;;;		    (cond
;;;		      ((eq dig (- #\rubout #/0))
;;;		       (ct_format *userout* "~%Please reenter your number: ")
;;;		       (read_integer st))
;;;		      (t num)))
;;;		 (setq num (+ (* num 10.) dig)))))
;;;	(cond 
;;;	    ((numberp inp) inp)
;;;	    (t (ct_format *errout* "Not a number ~A. Try Again:" inp)
;;;		(read_integer st)))))
;;;|#
;;;
;;;#+lispm
;;;       ;;;;;;;;;;;;
;;;(defun read_integer(st)
;;;       ;;;;;;;;;;;;
;;;
;;;  (let ((irt readtable))
;;;    (unwind-protect
;;;      (progn
;;;	(setq readtable (copy-readtable))
;;;	(set-syntax-from-description #/, 'si:whitespace)
;;;	(set-syntax-from-description #/) 'si:whitespace)
;;;	(set-syntax-from-description #/( 'si:whitespace)
;;;	(set-syntax-from-description #/` 'si:whitespace)
;;;	(set-syntax-from-description #/# 'si:whitespace)
;;;; 	(set-syntax-from-description #/_ 'si:slash)
;;;	(let ((inp (ct_read st)))
;;;	  (cond 
;;;	    ((numberp inp) inp)
;;;	    (t (ct_format *errout* "Not a number ~A. Try Again:" inp)
;;;	       (read_integer st)))))
;;;      (setq readtable irt))))
;;;#+franz
;;;       ;;;;;;;;;;;;
;;;(defun read_integer(st)
;;;       ;;;;;;;;;;;;
;;;
;;;  (ct_read st))
;;;
;;;
;;;	;;;;;;;
;;;(defun |lputint|(ar)
;;;	;;;;;;;
;;;
;;;  (let* ((printval (ct_send
;;;		    (cdr
;;;		      (assoc
;;;			`(lex_ident ,(uplowlist (exploden 'item)))
;;;			(ct_send ar 'locals)))
;;;		    'get_val nil))
;;;	 (*nopoint t)
;;;	 (base 10.))
;;;    (cond 
;;;	((and (consp printval) (memq (diana_nodetype_get printval) '(dn_enum_id dn_def_char)))
;;;	    (setq printval (implode (cadr (diana_get printval 'lx_symrep)))))
;;;	((and (consp printval) (eq (car printval) 'lex_string))
;;;	   (setq printval (implode (cadr printval)))))
;;;    (ct_princ printval *userout*)
;;;    (ct_princ " " *userout*)))
;;;
;;;	;;;;;;;;;;;;
;;;(defun |lput_linestr|(ar)
;;;	;;;;;;;;;;;;
;;;
;;;  (let ((printval (ct_send
;;;			  (cdr
;;;			    (assoc
;;;			      `(lex_ident ,(uplowlist (exploden 'item)))
;;;			      (ct_send ar 'locals)))
;;;			  'get_val nil)))
;;;
;;;    (do ((i 1 (1+ i)))
;;;	((> i (second (car (ct_send printval 'index_list)))))
;;;	(ct_tyo  (convert_char_to_integer
;;;		  (ct_send
;;;		      (ct_send printval 'get_val `(,i))
;;;		      'get_val nil)) *userout*))
;;;    (ct_terpri *userout*)))
;;;
;;;	;;;;;;;;;;;;
;;;(defun |lputstr|(ar)
;;;	;;;;;;;;;;;;
;;;
;;;  (let ((printval (ct_send
;;;			  (cdr
;;;			    (assoc
;;;			      `(lex_ident ,(uplowlist (exploden 'item)))
;;;			      (ct_send ar 'locals)))
;;;			  'get_val nil)))
;;;
;;;    (do ((i 1 (1+ i)))
;;;	((> i (second (car (ct_send printval 'index_list)))))
;;;	(ct_tyo  (convert_char_to_integer
;;;		  (ct_send
;;;		      (ct_send printval 'get_val `(,i))
;;;		      'get_val nil)) *userout*))
;;;    ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; code to test the various advising facilities. plus debugging pragmas.

	;;;;;;;;;
(defun |ada_break|(args)
	;;;;;;;;;

  (cond ((eq  (caar args) 'lex_string)(eval `(break ,(implode (cadar args)))))))

	;;;;;;;;;
(defun |ada_error|(args)
	;;;;;;;;;

  (cond ((eq  (caar args) 'lex_string)(eval `(ferror ,(implode (cadar args)))))))

	;;;;;;;
(defun |newline|(args)
	;;;;;;;

  (ct_terpri *userout*))

	;;;;;
(defun |write|(args)
	;;;;;

    (do ((items args (cdr items)))
	((null items))
	(cond
	    ((numberp (car items)) (ct_princ (car items) *userout*))
	    ((eq (caar items) 'lex_string)
	     (ct_princ (implode (cadr (car items))) *userout*))
	    ((eq (caar items) 'dn_used_name_id)
		(cond
		    ((eq (diana_nodetype_get (diana_get (car items) 'sm_defn)) 'dn_enum_id)
			(ct_princ
			  (implode (cadr (diana_get (car items) 'lx_symrep)))
			  *userout*))
		    (t (ct_princ
			   (ct_send 
			       (cdr (assoc 
					(diana_get (car items) 'lx_symrep)
					(ct_send *activation* 'locals)))
			       'current_value) *userout*))))
	    (t (lose 'be_batw 'write
		     ()
		     '("bad arg to write ~A" (car items)))))))

       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun massage_annotation_parameters(args)
       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    (do ((items args (cdr items))
	 (annotation_parameters nil))
	((null items) (reverse annotation_parameters)) 
	(cond
	    ((numberp (car items)) (ct_push (car items) annotation_parameters))
	    ((and (consp (car items))(eq (caar items) 'lex_string))
	     (ct_push (implode (cadr (car items)))annotation_parameters))
	    ((and (diana_nodep (car items))
		  (eq (diana_nodetype_get (car items)) 'dn_used_name_id))
		(cond
		    ((eq
		       (diana_nodetype_get (diana_get (car items) 'sm_defn))
		       'dn_enum_id)
			(ct_push
			  (implode (cadr (diana_get (car items) 'lx_symrep)))
			  annotation_parameters))
		    (t (ct_push
			 (cdr (assoc 
				(diana_get (car items) 'lx_symrep)
				(ct_send *activation* 'locals)))
			 *userout*))))
	    (t (ct_push (car items) annotation_parameters)))))

       ;;;;;;;;;;;;;;;;;;;;
(defun massage_trace_params(args)
       ;;;;;;;;;;;;;;;;;;;;

    (do ((items args (cdr items))
	 (trace_parameters nil))
	((null items) (reverse trace_parameters)) 
	(cond
	    ((numberp (car items)) (ct_push (car items) trace_parameters))
	    ((and (consp  (car items))(eq (caar items) 'lex_string))
	     (ct_push (implode (cadr (car items))) trace_parameters))
	    (t (ct_push '*** trace_parameters)))))

(declare (special *tracedepth* *tracedfunctions* ))

       ;;;;;;;;;;;;;
(defun ada_monitorfn( name oldval newval index)
       ;;;;;;;;;;;;;

  (freshline *userout*)
  
  (let ((*nopoint t))
  (ct_format *userout* "*** Changing the value of ~A~A from ~A to ~A" name
          (cond ((null index) "")(t  index))
          (cond ((listp oldval)
		 (implode (cadr (diana_get oldval 'lx_symrep))))
		(t oldval))
	  (cond ((listp newval)
		 (implode (cadr (diana_get newval 'lx_symrep))))
		(t newval))))
  (freshline *userout*)
)

       ;;;;;;;;;;;
(defun ada_tracefn(name params)
       ;;;;;;;;;;;

  (freshline *userout*)
  (do ((i 0 (1+ i)))((= i *tracedepth*))(ct_princ "|.."))
  (%= *tracedepth* (1+ *tracedepth*))
  (ct_format *userout* "*** Entered ~A ~A" name (massage_trace_params params))
  (freshline *userout*)
)

       ;;;;;;;;;;;;;;;
(defun ada_traceexitfn(name params)
       ;;;;;;;;;;;;;;;

  (freshline *userout*)
  (%= *tracedepth* (1- *tracedepth*))
  (do ((i 0 (1+ i)))((= i *tracedepth*))(ct_princ "|.."))
  (ct_format *userout* "*** Exited  ~A ~A" name (massage_trace_params params))
  (freshline *userout*)
)

       ;;;;;;;;;;;
(defun ada_monitor fexpr (name)
       ;;;;;;;;;;;

       (let* ((nm (car name))
	      (nme (intern (implode (uplowlist (exploden nm)))
			   'user))
	      (frob (variable_advise_rec 'ada_monitorfn (cadr name) 'set)))
	 (putprop
	   nme
	   (cons frob
		 (delete frob (get nm 'ada_variable_advise)))
	   'ada_variable_advise)
	 
	 (ct_push nme *tracedfunctions*)
	     name))

       ;;;;;;;;;
(defun ada_trace fexpr (name)
       ;;;;;;;;;

       (mapc
	 #'(lambda(nm)
	     (let ((nme (intern (implode (uplowlist (exploden nm)))
				'user)))
 	       (putprop
		 nme
		 (cons 'ada_tracefn (delq 'ada_tracefn (get nm 'ada_advise)))
		 'ada_advise)
	       (putprop
		 nme
		 (cons 'ada_traceexitfn
		       (delq 'ada_traceexitfn (get nm 'ada_after_advise)))
		 'ada_after_advise)
	       (ct_push nme *tracedfunctions*)))
	     name))

       ;;;;;;;;;;;
(defun ada_unmonitor fexpr (name)
       ;;;;;;;;;;;

       (mapc
	 #'(lambda(nm)
	     (let ((nme (intern (implode (uplowlist (exploden nm)))
				'user))
		   (frob (variable_advise_rec 'ada_monitorfn nil 'set))) 
	       (setq *tracedfunctions* (delq nme *tracedfunctions*))
	       (putprop
		 nme
		 (delete frob (get nm 'ada_variable_advise))
		 'ada_variable_advise)
	       
	       ))
	 (or name *tracedfunctions*)))


       ;;;;;;;;;;;
(defun ada_untrace fexpr (name)
       ;;;;;;;;;;;

       (mapc
	 #'(lambda(nm)
	     (let ((nme (intern (implode (uplowlist (exploden nm)))
				'user))) 
	       (setq *tracedfunctions* (delq nme *tracedfunctions*))
	       (putprop
		 nme
		 (delq 'ada_tracefn (get nm 'ada_advise))
		 'ada_advise)
	       (putprop
		 nme
		 (delq 'ada_traceexitfn (get nm 'ada_after_advise))
		 'ada_after_advise)
	       ))
	 (or name *tracedfunctions*)))

       ;;;;;;;;;;;;;;;;;;;
(defun ada_exception_trace fexpr (name)
       ;;;;;;;;;;;;;;;;;;;

       (mapc
	 #'(lambda(nm)
	     (let ((nme (intern (implode (uplowlist (exploden nm)))
				'user)))
 	       (putprop
		 nme
		 (cons 'ada_excfn (delq 'ada_excfn (get nm 'ada_exception_advise)))
		 'ada_exception_advise)
	       (putprop
		 nme
		 (cons 'ada_excexitfn
		       (delq 'ada_excexitfn (get nm 'ada_exception_after_advise)))
		 'ada_exception_after_advise)
	       (ct_push nme *tracedfunctions*)))
	     name))

       ;;;;;;;;;;;;;;;;;;;;;
(defun ada_exception_untrace fexpr (name)
       ;;;;;;;;;;;;;;;;;;;;;

       (mapc
	 #'(lambda(nm)
	     (let ((nme (intern (implode (uplowlist (exploden nm)))
				'user))) 
	       (setq *tracedfunctions* (delq nme *tracedfunctions*))
	       (putprop
		 nme
		 (delq 'ada_excfn (get nm 'ada_exception_advise))
		 'ada_exception_advise)
	       (putprop
		 nme
		 (delq 'ada_excexitfn (get nm 'ada_exception_after_advise))
		 'ada_exception_after_advise)
	       ))
	 (or name *tracedfunctions*)))

       ;;;;;;;;;
(defun ada_excfn(name exc)
       ;;;;;;;;;

  (freshline *userout*)
  (ct_format *userout* "*** Subprogram ~A handling exception ~A"
	     name exc)
  (freshline *userout*)
)

       ;;;;;;;;;;;;;
(defun ada_excexitfn(name exc)
       ;;;;;;;;;;;;;

  (freshline *userout*)
  (ct_format *userout* "*** Subprogram ~A exited handler for exception ~A"
	     name exc)
  (freshline *userout*)
)

;;; eof
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
