;;; -*- mode:lisp;package:user;base:10.;fonts: cptfontb -*- ;;; $Header: /ct/interp/aggies.l,v 1.40 84/10/22 19:34:11 penny Exp $ ;;; ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; aggies.l ;;; ;;; Paul Robertson October 18, 1983 ;;; ;;; ;;; ;;; The C*T Ada Interpreters Static Semantic support ;;; ;;; ;;; ;;; 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: ;;; ;;; Miller, 1982. The C*T Ada Tutor: Guide to the Implementation. ;;; ;;; Charniak et al., 198?. Artificial Intelligence Programming. ;;; ;;; ;;; ;;; The following code assumes familiarity with the above. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Ensure presence of needed files. (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)) (eval-when (compile load eval) (ct_load 'time)) ;Timing functions. (eval-when (compile load eval) (ct_load 'diana)) ; Diana tools. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Compiler Declarations and Global Variables -- #+franz (declare (macros t)) (declare (ct_includef 'intrpdcl)) ; get the specials (eval-when (compile load eval) (ct_load 'ferec)) ; get the macros etc. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Externally Call-able Functions/Macros -- ;;; Static semantic code schemas are structured as follows. ;;; Body contains lisp code that returns a piece of diana tree or nil. ;;; The main way of building a diana tree is with the sc_diana functon. ;;; Simple node will consist only of these nodes. sc_diana looks like this... ;;; (sc_diana dn_foo slotname code slotname code slotname code .. .. .. ..) ;;; The above example creates a diana node with the names slots, and calls the ;;; appropriate code to fill the slots. One reason why this function should be ;;; used is that it hides the internal representation of a diana node making ;;; future modifications easy (which would be necessary for say a production ;;; compiler. ;;; The abstract syntax is available for inclusion in the diana tree or ;;; other in a free variable called *abstract_syntax*. This variable may be ;;; altered by the code for effeciency reasons without intefering with the ;;; parsing process. Syntax nodes that do not have ssemantics code will ;;; produce abstract syntax subtree's. To return a null node have a ssemantic ;;; property that returns nil. ;;; Section by pozsvath for (array & record) aggregate normalization ;;; If dn can be normalized, normalize it. Otherwise stick it on the ;;; normalize waiting list. (defun get_real_type (dn) (cond ((null dn) nil) (t (setq dn (extract_basetype dn t)) (cond ((null dn) nil) ((eq (diana_nodetype_get dn) 'dn_access) (get_real_type (diana_get dn 'as_constrained))) ; ((eq (diana_nodetype_get dn) 'dn_constrained) ; (get_real_type dn)) ((eq (diana_nodetype_get dn) 'dn_void) nil) (t dn))))) ;;;;;;;;;;;;;;;;;;; (defun normalize_aggregate(dn) ;;;;;;;;;;;;;;;;;;; (let ((type (get_real_type (diana_get dn 'sm_exp_type)))) (cond ((dynamic_aggregatep dn)) (type (ct_selectq (diana_nodetype_get type) (dn_enum_literal_s ;; ++The errset was added in case the dn is severely confused ;; (such as (...others='a') which causes type to be a ;; dn_enum_literal_s. (cond ((null (errset (normalize_enum_literal_aggregate dn) nil)) (cannot_normalize dn)))) (dn_record (normalize_record_aggregate dn)) (dn_array (cond ((dynamic_aggregatep dn)) ((eq '*bad_index_list* (*catch '*bad_index_list* (cond ((constrained_arrayp dn) (normalize_constrained_array_aggregate dn (create_index_list (find_constraint_for2 (diana_get dn 'sm_exp_type))))) (t (normalize_unconstrained_array_aggregate dn))))) (cond ((eq '*bad_index_list* (*catch '*bad_index_list* (normalize_unconstrained_array_aggregate dn))) ))))) ((dn_private_type_id dn_l_private_type_id) (semgripe 'cant_mix_aggies_with_privates)) (otherwise (lose 'fe_batna ; BadAttributeToNormalizeAggregate ++ should 'normalize_aggregate)))) ; never happen!!! (t (ct_push dn *awaiting_aggregate_normalization*))))) (defun return_dynamic_aggregate (dn choices val &optional index_list) (let ((index_list (cond (index_list index_list) (t (*catch '*bad_index_list* (cond ((constrained_arrayp dn) (create_index_list (find_constraint_for2 (diana_get dn 'sm_exp_type)))))))))) (cond ((null (diana_nodep val)) (semgripe 'cannot_normalize (diana_get val 'lx_srcpos)) (*throw '*cannot_normalize* '*cannot_normalize*))) (cond ((eq (diana_nodetype_get val) 'dn_aggregate) (cond ((cdr index_list) (normalize_constrained_array_aggregate val (cdr index_list))) (t (normalize_aggregate val))))) (diana_put dn (dynamic_range_rec (car choices) val) 'sm_normalized_comp_s))) (defun dynamic_aggregatep (dn &optional index_list) (let ((seq (diana_get dn 'as_list))) (cond ((and (named_aggregatep seq) (null (cdr seq))) (let* ((choices (diana_get (diana_get (car seq) 'as_choice_s) 'as_list)) (val (diana_get (car seq) 'as_exp)) (firstchoice (eval_named_choice (car choices)))) (cond ((null (cdr choices)) (cond ((and (consp firstchoice) (or (diana_nodep (car firstchoice)) (diana_nodep (cadr firstchoice)))) (return_dynamic_aggregate dn choices val index_list)) ((diana_nodep firstchoice) (ct_selectq (diana_nodetype_get firstchoice) (dn_others) ((dn_enum_id dn_def_char dn_character_literal)) (otherwise ; must be a dynamic_range (return_dynamic_aggregate dn choices val index_list)))))))))))) (defun return_range (rng) (cond ((and (diana_node_accepts_attributep rng 'as_exp1) (diana_node_accepts_attributep rng 'as_exp2)) (let ((e1 (return_index (diana_get rng 'as_exp1) nil)) (e2 (return_index (diana_get rng 'as_exp2) nil))) `(,e1 ,e2))) ((eq (diana_nodetype_get rng) 'dn_subtype_id) (return_range (diana_get rng 'sm_type_spec))) ((eq (diana_nodetype_get rng) 'dn_constrained) (cond ((and (diana_get rng 'as_constraint) (null (eq (diana_nodetype_get (diana_get rng 'as_constraint)) 'dn_void))) (return_range (diana_get rng 'as_constraint))) (t (return_range (diana_get rng 'as_name))))) ((eq (diana_nodetype_get rng) 'dn_type_id) (return_range (diana_get rng 'sm_type_spec))) ((eq (diana_nodetype_get rng) 'dn_enum_literal_s) `(,(diana_get (car (diana_get rng 'as_list)) 'sm_pos) ,(diana_get (car (last (diana_get rng 'as_list))) 'sm_pos))) ((and (eq (diana_nodetype_get rng) 'dn_used_name_id) (diana_get rng 'sm_defn)) (return_range (diana_get rng 'sm_defn))) (t nil))) ;;;CROCK++ (defun find_constraint_for2 (dn) (let ((res (find_constraint_for dn))) (cond ((eq (diana_nodetype_get res) 'dn_subtype_id) (find_constraint_for (diana_get res 'sm_type_spec))) ((eq (diana_nodetype_get res) 'dn_derived) (find_constraint_for2 (diana_get res 'as_constrained))) (t res)))) ;;;;;;;;;;;;;;;;; (defun create_index_list (range_list) ;;;;;;;;;;;;;;;;;; (mapcar #'return_range (diana_get range_list 'as_list))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun normalize_enum_literal_aggregate (dn) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (let* ((asl (diana_get dn 'as_list)) (smexp (diana_get dn 'sm_exp_type));list of lits (normalized nil) (numsm (length (diana_get smexp 'as_list))) (numasl (length asl))) (cond ((not (eq numsm numasl)) (semgripe 'wrong_number_of_values_in_rep_clause)) ((eq (diana_nodetype_get (car asl)) 'dn_named);needs normalizing (let* ((norm (do ((i 0 (1+ i)) (n nil)) ((= numasl i) n) (setq n (append '(nil) n)))));list of of right length (mapc #'(lambda (nam) (let ((exp (diana_get nam 'as_exp));expression (id (diana_get (car (diana_get (diana_get nam 'as_choice_s) 'as_list)) 'lx_symrep))) ;lex_ident (cond ((neq (do ((j 0 (1+ j)) (count 0)) ((= j numasl) count) (cond ((equal id (diana_get (nth j (diana_get smexp 'as_list)) 'lx_symrep)) (rplaca (nthcdr j norm) exp) (setq count (1+ count))))) 1) (semgripe 'incorrect_name_in_aggregate ))))) asl) (mapc #'fe_static_eval norm) (ascending_orderp norm) (diana_put dn (sc_diana dn_exp_s as_list norm) 'sm_normalized_comp_s))) (t ;map down asl and get as_exp (mapc #'(lambda (exp) (setq normalized (append normalized (list exp)))) asl) (mapc #'fe_static_eval normalized) (ascending_orderp normalized) (diana_put dn (sc_diana dn_exp_s as_list normalized) 'sm_normalized_comp_s)))) (%= *awaiting_aggregate_disambiguation* (delq dn *_*)) dn) ;;;;;;;;;;;;;;;; (defun ascending_orderp (lt) ;;;;;;;;;;;;;;;; (let ((currentval (diana_get (first lt) 'sm_value))) (mapc #'(lambda (nuval) (cond (nuval (let ((nval (diana_get nuval 'sm_value))) (cond ((> nval currentval) (setq currentval nval)) (t (semgripe 'integer_codes_in_wrong_order))))))) (cdr lt)))) ;;;;;;;;;;;;;;;;;;;;;;; (defun constrained_arrayp (dn) ;;;;;;;;;;;;;;;;;;;;;;; (let ((type (diana_get dn 'sm_exp_type))) (and (arrayp type) (let ((indices (find_constraint_for2 type))) (cond ((and indices (eq (diana_nodetype_get indices) 'dn_dscrt_range_s)) (let ((il (diana_get indices 'as_list)) (constrainedp t)) (mapc #'(lambda(i) (cond ((eq (diana_nodetype_get i) 'dn_index) (setq constrainedp nil)))) il) constrainedp)) (t nil)))))) ;;; This gets a diana node of type dn_aggregate (an array), which can ;;; can contain dn_nameds (things like (1 | 2 | 3..7 => 'a')). It returns ;;; a diana node which is an expansion (like (1 => 'a' 2 => 'a' etc.)). ;;; index_list is a list of lists of dimension boundaries. So for example, ;;; a(1..3,2..4,0..9) would be represented as ((1 3) (2 4) (0 9)) ;;; index_list=nil for an unconstrained array ;;;;;;;;;;;;;;;; (defun named_aggregatep (seq) ;;;;;;;;;;;;;;;; (eq (diana_nodetype_get (car seq)) 'dn_named)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun normalize_unconstrained_array_aggregate (dn) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Creates index_list and then normalizes array (cond ((dynamic_aggregatep dn)) (t (*catch '*cannot_normalize* (diana_put dn ;; Should do a catch in case the aggregate is hopeless (get_index_list_from_unconstrained_aggie (diana_get dn 'as_list) (length (diana_get (find_constraint_for2 dn) 'as_list))) 'ct_index_list) (cond ((null_indexlist (diana_get dn 'ct_index_list)) (*throw '*cannot_normalize* '*cannot_normalize*))) (normalize_constrained_array_aggregate dn (diana_get dn 'ct_index_list)) )))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun get_index_list_from_unconstrained_aggie (meaty_part depth) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (cond ((named_aggregatep meaty_part) (let ((smallest nil) (largest nil) (rest_of_il nil)) (mapc #'(lambda (memb) (cond ((null (and (diana_nodep memb) (eq (diana_nodetype_get memb) 'dn_named))) (semgripe 'cannot_disabiguate (diana_get memb 'lx_srcpos))) (t (cond ((and (eq (diana_nodetype_get (diana_get memb 'as_exp)) 'dn_aggregate) (null rest_of_il) (null (eq depth 1))) (setq rest_of_il (get_index_list_from_unconstrained_aggie (diana_get (diana_get memb 'as_exp) 'as_list) (1- depth))))) (mapc ; Iterate down the choices (1|2|3..4,etc) #'(lambda (choice) (setq choice (eval_named_choice choice)) (cond ((numberp choice) (%= smallest (ct_min smallest (return_index choice))) (%= largest (ct_max largest (return_index choice)))) ((consp choice) (cond ((<= (return_index (car choice)) (return_index (cadr choice)) (%= smallest (ct_min smallest (return_index (car choice)))) (%= largest (ct_max largest (return_index (cadr choice)))))))) ((diana_nodep choice) (ct_selectq (diana_nodetype_get choice) (dn_others (semgripe 'others_in_unconstrained_aggie) (*throw '*cannot_normalize* '*cannot_normalize*)) ((dn_enum_id dn_def_char dn_character_literal) (%= smallest (ct_min smallest (return_index choice))) (%= largest (ct_max largest (return_index choice)))) (otherwise ; Illegal choice (dynamic_range choice)))) (t (dynamic_range choice)))) (diana_get ; Extract choices from diana node (diana_get ; DN_CHOICE_S memb ; DN_NAMED 'as_choice_s) 'as_list))))) meaty_part) (cons (list smallest largest) rest_of_il))) (t ;Must be sequenced (cons (list 1 ;CROCKERY!!!++ (length meaty_part)) (cond ((and (eq (diana_nodetype_get (car meaty_part)) 'dn_string_literal) (null (eq depth 1))) (cons (list 1 (length (cadr (diana_get (car meaty_part) 'lx_symrep)))) nil)) ((and (eq (diana_nodetype_get (car meaty_part)) 'dn_aggregate) (null (eq depth 1))) (get_index_list_from_unconstrained_aggie (diana_get (car meaty_part) 'as_list) (1- depth)))))))) ;;;;;;; (defun ct_max (x y) ;;;;;;; (cond ((null x) y) ((null y) x) (t (max x y)))) ;;;;;; (defun ct_min (x y) ;;;;;; (cond ((null x) y) ((null y) x) (t (min x y)))) ;;;;;;;;;;;;;; (defun null_indexlist (il) ;;;;;;;;;;;;;; (null (mapcan #'(lambda(dim) (cond ((null (car dim)) nil) (t (list (car dim)))) (cond ((null (cadr dim)) nil) (t (list (cadr dim))))) il))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun normalize_constrained_array_aggregate (dn index_list) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (*catch '*cannot_normalize* (cond ((null_indexlist index_list) (normalize_unconstrained_array_aggregate dn)) ((dynamic_aggregatep dn index_list)) (t (diana_put dn (sc_diana dn_exp_s as_list (cond ((named_aggregatep (diana_get dn 'as_list)) (normalize_named_constrained_array_aggregate (diana_get dn 'as_list) index_list)) (t (normalize_seq_constrained_array_aggregate (diana_get dn 'as_list) index_list)))) 'sm_normalized_comp_s) (cond ((memq nil (diana_get (diana_get dn 'sm_normalized_comp_s) 'as_list)) (semgripe 'array_aggie_short)) ) index_list)))) (defun arragg_rplac_nth (index starti res val) (agg_rplac_nth (1+ (- index starti)) res val)) (defun eval_named_choice(dn) (let ((res (agg_static_eval dn))) (cond ((null (diana_nodep res)) res) (t (ct_selectq (diana_nodetype_get res) (dn_range `(,(eval_named_choice (diana_get dn 'as_exp1)) ,(eval_named_choice (diana_get dn 'as_exp2)))) (dn_type_id (eval_named_choice (diana_get res 'sm_type_spec))) (dn_subtype_id (eval_named_choice (diana_get res 'sm_type_spec))) (dn_constrained (eval_named_choice (find_constraint_for2 dn))) (dn_dscrmt_id nil) (dn_enum_literal_s `(,(car (diana_get res 'as_list)) ,(car (last (diana_get res 'as_list))))) (otherwise res)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun normalize_named_constrained_array_aggregate (meaty_part index_list) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (let ((val nil) (res (expand_array index_list))) (mapc #'(lambda (memb) ; (let ((val (diana_get memb 'as_exp))) (cond ((null (and (diana_nodep memb) (eq (diana_nodetype_get memb) 'dn_named))) (semgripe 'mix_namd_n_seq) (throw '*cannot_normalize* '*cannot_normalize)) (t (setq val (diana_get memb 'as_exp)) (cond ((null (diana_nodep val)) (semgripe 'cannot_normalize (diana_get val 'lx_srcpos)) (*throw '*cannot_normalize* '*cannot_normalize*))) (cond ((eq (diana_nodetype_get val) 'dn_aggregate) (cond ((cdr index_list) (normalize_constrained_array_aggregate val (cdr index_list))) (t (normalize_aggregate val))))) (mapc ; Iterate down the choices (1|2|3..4,etc) #'(lambda (choice) (setq choice (eval_named_choice choice)) (cond ((numberp choice) (arragg_rplac_nth (return_index choice) (caar index_list) res val)) ((consp choice) (map_over_range 'arragg_rplac_nth (return_index (car choice)) (return_index (cadr choice)) (caar index_list) res val)) ((diana_nodep choice) (ct_selectq (diana_nodetype_get choice) (dn_others (ct_subst val nil res)) ((dn_enum_id dn_def_char dn_character_literal) (arragg_rplac_nth (return_index choice) (caar index_list) res val)) (otherwise ; Illegal choice (dynamic_range choice val)))))) (diana_get ; Extract choices from diana node (diana_get memb 'as_choice_s) 'as_list))))) meaty_part) res)) (defun agg_static_eval (dn) (*catch '*diana_node_not_static_expression* (static_eval dn t))) (defun dynamic_range (dn val) (*throw '*cannot_normalize* '*cannot_normalize*)) (defun map_over_range (fn starting ending &rest other_args) (do ((c starting (1+ c))) ((> c ending)) (apply fn (cons c other_args)))) (defun normalize_seq_constrained_array_aggregate (meaty_part index_list) (let ((res (expand_array index_list))) (map #'(lambda (membs cpp) (cond ((eq ; When done going down the array in order (diana_nodetype_get (car membs)) 'dn_named) (let ((val (diana_get (car membs) 'as_exp))) (cond ((eq (diana_nodetype_get val) 'dn_aggregate) (cond ((cdr index_list) (normalize_constrained_array_aggregate val (cdr index_list))) (t (normalize_aggregate val))))) ;; must be an OTHERS (cond ((null (eq (diana_nodetype_get (car (diana_get (diana_get (car membs) 'as_choice_s) 'as_list))) 'dn_others)) (semgripe 'mix_namd_n_seq))) (ct_subst val nil res))) ((eq ; Multi-dimensional array (diana_nodetype_get (car membs)) 'dn_aggregate) (cond ((null (cdr index_list)) ; Aggregate (normalize_aggregate (car membs)) (rplaca cpp (car membs))) (t ; Aggregate for other dimension (normalize_constrained_array_aggregate (car membs) (cdr index_list)) (rplaca cpp (car membs)))) (setq cpp (cdr cpp))) (t ; A sequenced literal (cond ((car index_list) ; Constrained array type (rplaca cpp (car membs))) (t (lose 'fe_uattna ;; Unconstr.ArrayTypeToNormalizeArrayAggregate ;; Should never happen! ++ 'normalize_constrained_array_aggregate)))))) meaty_part res) res)) ;;; Takes an array which is a list of ranges of each dimension and expands ;;; it into a list with the number of elements in the range of the first ;;; dimension with each element being the rest of the dimensions. This ;;; comment is longer than its corresponding code. ;;;;;;;;;;;; (defun expand_array (index_list) ;;;;;;;;;;;; (cond ((null index_list) nil) (t (let ((lb (return_index (caar index_list) nil)) (ub (return_index (cadar index_list) nil))) (cond ((and (numberp lb) (numberp ub)) (do ((c (caar index_list) (1+ c)) (res nil (cons nil res))) ((> c (cadar index_list)) res))) (t (bad_index_list))))))) (defun bad_index_list () (*throw '*bad_index_list* '*bad_index_list*)) ;;; Substitute (dangerously) every occurance of `deletee' with `addee' in ;;; the top level of `object_of_replacement' ;;;;;;;; (defun ct_subst (addee deletee object_of_replacement) ;;;;;;;; (map #'(lambda (whats_left) (cond ((eq (car whats_left) deletee) (rplaca whats_left addee)))) object_of_replacement)) ;;; Gets a lisp number out of a diana node of type DN_NUMERIC_LITERAL ;;;;;;;;;;;; (defun return_index (dn &optional (die t)) ;;;;;;;;;;;; (let ((val (cond ((diana_nodep dn) (fe_static_eval dn)) (t dn)))) (cond ((eq val '*diana_node_not_static_expression*) (setq val dn))) (cond ((diana_nodep val) (ct_selectq (diana_nodetype_get val) (dn_numeric_literal (numval (diana_get val 'lx_numrep))) (dn_character_literal (caadr (diana_get val 'lx_symrep))) (dn_def_char (1+ (diana_get val 'sm_pos))) (dn_enum_id (diana_get val 'sm_pos)) (otherwise (cond (die (sgripe `(,(ct_format nil "The aggregate on line ~A cannot be normalized." (source_region%linstart (diana_get val 'lx_srcpos)))) '((lrmref "LRM" (lrmsec 13 3 nil) (lrmpar 4 nil)) (lrmref "LRM" (lrmsec 13 3 nil) (lrmpar 5 nil)))) (bad_index_list)) (T (bad_index_list)))))) (t val)))) ;;; Replace the `int'th element of list `list' with `nuthing'. `int' must ;;; start with 1. ;;;;;;;;; (defun agg_rplac_nth (int list nuthing &optional (complain t)) ;;;;;;;;; (cond ((lessp int 0) (cond (complain (*throw '*cannot_normalize* '*cannot_normalize*) (semgripe 'array_aggie_index_too_low)))) ((greaterp int (length list)) (cond (complain (*throw '*cannot_normalize* '*cannot_normalize*) (semgripe 'array_aggie_index_too_high)))) (t #+franz (rplaca (nth int list) nuthing) ; starts with 1 #+lispm (do ((res list (cdr res)) (i int (1- i))) ((eq i 1) (rplaca res nuthing)))))) ;;; Replace the `int'th element of list `list' with `nuthing'. `int' must ;;; start with 1. If int is greater than the length of the list, make ;;; the list larger with nils ;;;;;;;;;;;;;;;;;;;; (defun agg_rplac_nth_create (int list nuthing) ;;;;;;;;;;;;;;;;;;;; (cond ((lessp int 0) (semgripe 'array_aggie_index_too_low)) (t (do ((res list (cdr res)) (i int (1- i))) ((eq i 1) (rplaca res nuthing)) (cond ((null (cdr res)) (rplacd res (cons nuthing nil)))))))) (defun offset_of (n l) (mod (- (length l) (length (memq n l))) (length l))) (defun merge_out_nils (r d) (map #'(lambda (x y) (cond ((car x)) ((cadddr (car y)) (rplaca x (cadddr (car y)))) (t (semgripe 'rec_aggie_short)))) r d) r) (defun cannot_normalize (dn) (sgripe `(,(ct_format nil "The aggregate on line ~A cannot be normalized." (source_region%linstart (diana_get dn 'lx_srcpos)))) '((lrmref "LRM" (lrmsec 13 3 nil) (lrmpar 4 nil)) (lrmref "LRM" (lrmsec 13 3 nil) (lrmpar 5 nil))))) ;;; Normalizing record aggregates consists of three phases: ;;; 1). Finding the discriminants and their values ;;; 2). Using the information from the first step, which is contained ;;; in an alist of the form `((,dscrmnt1 ,value1) ... (,dscrmntN ,valueN)), ;;; to create the offset alist, a list, in order containing ;;; triples of the form (, , ,). ;;; 3). Using the information from step 2, fill a list with N elements with the ;;; appropriate values (defun normalize_record_aggregate (agg) (let* ((recdef (extract_basetype (diana_get agg 'sm_exp_type) t)) (dscrmt_aggie (find_constraint_for2 (diana_get agg 'sm_exp_type))) (dscrmt_aggie (cond ((null (diana_nodep dscrmt_aggie)) nil) (t (ct_selectq (diana_nodetype_get dscrmt_aggie) (dn_record (setq recdef dscrmt_aggie) nil) (dn_dscrmt_aggregate (diana_get dscrmt_aggie 'as_list)))))) (dscrmts (find_dscrmt_values (diana_get agg 'as_list) recdef dscrmt_aggie )) (offset_alist (reverse (build_list_of_triples 1 dscrmts (cond (dscrmts (append (diana_get (diana_get recdef 'sm_discriminants) 'as_list) (diana_get recdef 'as_list))) (t (diana_get recdef 'as_list)))))) (res (mapcar #'(lambda (x) nil) offset_alist))) (%= res (fill_in_slots_to_record_aggregate res offset_alist (cond (dscrmt_aggie (append (mapcar #'cadr dscrmts) (diana_get agg 'as_list))) (t (diana_get agg 'as_list))) nil)) (%= res (merge_out_nils res offset_alist)) (diana_put agg (sc_diana dn_exp_s as_list res) 'sm_normalized_comp_s) )) ;;; ;;; Finds the discriminant values. ;;; Produces an alist. (defun find_dscrmt_values (agg recdef dscrmt_aggie) (cond ((and dscrmt_aggie (diana_get recdef 'sm_discriminants)) (let ((dscrmts (mapcan #'(lambda (var) (mapcar #'(lambda (id) (diana_get id 'lx_symrep)) (diana_get var 'as_id_s))) (diana_get (diana_get recdef 'sm_discriminants) 'as_list)))) (mapcar #'(lambda (dscrmt val) `(,dscrmt ,val)) dscrmts dscrmt_aggie))) ((diana_get recdef 'sm_discriminants) (let* ((dscrmts (mapcan #'(lambda (var) (mapcar #'(lambda (id) (diana_get id 'lx_symrep)) (diana_get var 'as_id_s))) (diana_get (diana_get recdef 'sm_discriminants) 'as_list))) (offset_alist (reverse (build_list_of_triples 1 nil (append (diana_get (diana_get recdef 'sm_discriminants) 'as_list) ; (diana_get recdef 'as_list) )))) (res (mapcar #'(lambda (x) nil) offset_alist))) (%= res (fill_in_slots_to_record_aggregate res offset_alist agg t)) (setq res (merge_out_nils res offset_alist)) (mapcar #'(lambda (dscrmt val) `(,dscrmt ,val)) dscrmts res))))) (defun is_in (inval choice_s) (do ((val (agg_static_eval inval)) (rest choice_s (cdr rest))) ((null rest) nil) (cond ((or (eq (diana_nodetype_get (car rest)) 'dn_others) (eq (agg_static_eval (car rest)) val)) (return t))))) (defun build_list_of_triples (stoffset dlist vars) (let ((ct stoffset) (offset_alist nil)) (mapc #'(lambda (elem) (ct_selectq (diana_nodetype_get elem) (dn_variant_part (let* ((name (diana_get (diana_get elem 'as_name) 'lx_symrep)) (val (cadr (assoc name dlist)))) (do ((variants (diana_get (diana_get elem 'as_variant_s) 'as_list) (cdr variants))) ((null variants) ()) (cond ((is_in val (diana_get (car variants) 'as_choice_s)) (let* ((subres (build_list_of_triples ct dlist (diana_get (diana_get (car variants) 'as_record) 'as_list)))) (%= offset_alist (append subres *_*)) (%= ct (+ *_* (length subres)))) (return)))))) (dn_var (mapc #'(lambda (avar) (ct_push `(,(diana_get avar 'lx_symrep) ,ct ,(diana_get elem 'as_type_spec) ,(diana_get elem 'as_object_def)) offset_alist) (%= ct (1+ *_*))) (diana_get elem 'as_id_s))) (dn_null_comp) (otherwise (cannot_normalize elem)))) vars) offset_alist)) (defun fill_in_slots_to_record_aggregate (res offset_alist agg limited_res) (do ; Iterate down dn's as_list ((rest_of_agg agg (cdr rest_of_agg)) (cpp res) (start_unsequenced nil)) ((or (and (null start_unsequenced) (null cpp)) (null rest_of_agg)) res) (cond ((eq ; When done going down record in order (diana_nodetype_get (car rest_of_agg)) 'dn_named) (setq start_unsequenced t) (let ((val (diana_get (car rest_of_agg) 'as_exp))) (mapcar ; Iterate down the choices #'(lambda (choice) (ct_selectq (diana_nodetype_get choice) (dn_others ; Is it an "others"? (cond ((eq (diana_nodetype_get val) 'dn_aggregate) (diana_put val (caddr (nth (offset_of nil res) offset_alist)) 'sm_exp_type) (normalize_aggregate val))) (ct_subst val nil res)) (dn_selected ; like aField => someThing (let* ((pair (assoc (diana_get (diana_get choice 'as_designator_char) 'lx_symrep) offset_alist)) (offset (cadr pair)) (type (caddr pair))) (cond ((eq (diana_nodetype_get val) 'dn_aggregate) (diana_put val type 'sm_exp_type) (normalize_aggregate val))) (cond (limited_res (cond ((and offset (<= offset (length res))) (agg_rplac_nth offset res val nil)))) (offset (agg_rplac_nth offset res val nil)) (t (sgripe `(,(ct_format nil "The selected component on line ~A is unknown." (source_region%linstart (diana_get choice 'lx_srcpos)))) '((lrmref "LRM" (lrmsec 4 3 1) (lrmpar 1 nil)) (lrmref "LRM" (lrmsec 4 3 1) (lrmpar 4 6)))))))) (dn_used_name_id (let* ((pair (assoc (diana_get choice 'lx_symrep) offset_alist)) (offset (cadr pair)) (type (caddr pair))) (cond ((eq (diana_nodetype_get val) 'dn_aggregate) (diana_put val type 'sm_exp_type) (normalize_aggregate val))) (cond (limited_res (cond ((and offset (<= offset (length res))) (agg_rplac_nth offset res val nil)))) (offset (agg_rplac_nth offset res val nil)) (t (sgripe `(,(ct_format nil "The selected component on line ~A is unknown." (source_region%linstart (diana_get choice 'lx_srcpos)))) '((lrmref "LRM" (lrmsec 4 3 1) (lrmpar 1 nil)) (lrmref "LRM" (lrmsec 4 3 1) (lrmpar 4 6)))))))) (otherwise ; Illegal choice ++ (lose 'fe_ictnra 'normalize_record_aggregate)))) (diana_get ; Extract choices from diana node (diana_get ; DN_CHOICE_S (car rest_of_agg) ; DN_NAMED 'as_choice_s) 'as_list) )) ) ((eq ; Multi-dimensional array (diana_nodetype_get (car rest_of_agg)) 'dn_aggregate) (diana_put (car rest_of_agg) (caddr (ct_nth (1+ (- (length res) (length cpp))) offset_alist)) 'sm_exp_type) (normalize_aggregate (car rest_of_agg)) (rplaca cpp (car rest_of_agg)) ; PHROB !!!++ (setq cpp (cdr cpp))) (start_unsequenced (semgripe 'el_out_of_order_aggie)) (t ; A sequenced literal (rplaca cpp (car rest_of_agg)) (setq cpp (cdr cpp)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; disambiguate aggregates and put in their type specs. ;;;;;;;;;;;;;;;;;;;;;;; (defun dissambiguate_aggregate (dn mom) ;;;;;;;;;;;;;;;;;;;;;;; (let ((my_type (diana_get dn 'sm_exp_type))) (cond (my_type (%= *awaiting_aggregate_disambiguation* (delq dn *_*)) (normalize_aggregate dn))))) ;;;EOF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;