;;; -*- mode:lisp;package:user;base:10.;fonts:(cptfontb) -*- ;;; $Header: /ct/interp/pnorms.l,v 1.8 84/05/16 19:32:30 penny Exp $ ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; pnorms.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. ;;; takes a diana node dn that must be a subprogram call. Combines the ;;; definition with the actuals to provide a list of normalized parameters. ;;; the normalized parameters are added to the diana node dn as the semantic ;;; attribute sm_normalized_param_s. ;;;;;;;;;;;;;;;; (defun normalize_params(dn) ; normalize parameters for dn. ;;;;;;;;;;;;;;;; (let ((actuals (let ((apas (diana_get dn 'as_param_assoc_s))) (and apas (diana_get apas 'as_list)))) (formals (let* ((asnam (diana_get dn 'as_name)) (smdef (and asnam (subprog_bit (diana_get asnam 'sm_defn)))) ; definition's (smsp (and smdef (diana_get smdef 'sm_spec))); spec's (apas (and smsp (diana_get smsp 'as_param_s)))) apas)) (parampos 1) (unsequenced nil) (normalized nil)) (cond ;; if formals is nil and actuals non nil, delay normalization until ;; later because we haven't got a spec installed for this function yet. ( ;;(and actuals (null formals)) -- putback when operators interned. (and actuals (null formals) (not (let ((nm (diana_get dn 'as_name))) (and nm (eq (diana_nodetype_get nm) 'dn_used_bltn_op))))) (ct_push dn *awaiting_parameter_normalization*) dn) (t ;;otherwise go ahead and normalize it. (do ((aps actuals (cdr aps)) (fps (extract_formal_id_s formals)));returns a list of pairs. ((null aps) (prog1 dn (let ((nparams (append (reverse normalized) (sequence_kwp unsequenced fps parampos t)))) (check_assignable_out_parameters (extract_formal_id_s formals) nparams) (diana_put dn (sc_diana dn_exp_s as_list nparams) 'sm_normalized_param_s)))) (ct_selectq (diana_nodetype_get (first aps)) (dn_assoc (let ((formpos (find_formal (first aps) fps parampos))) (cond ((zerop formpos) ;(break unmatched-keyword) (comment (semgripe `unmatch_keyword_param))) (t (ct_push `(,formpos ,(first aps)) unsequenced))))) (otherwise (%= fps (cdr fps)) ; this formal is accounted for. (%= parampos (1+ *_*)) ; (ct_push (copy_dn (car aps)) normalized) (ct_push (car aps) normalized)))))))) (defun check_assignable_out_parameters (fpl al) (mapc #'(lambda (f a) (cond ((eq (diana_nodetype_get (car f)) 'dn_in_id)) ((assignable_p a) ) (t (semgripe 'actual_parameter_out_formal_not_assignable (implode (lowuplist (cadr (diana_get (car f) 'lx_symrep)))))))) fpl al)) ;;;;;;;;;;;;;;;;;;; (defun extract_formal_id_s(fpl) ;;;;;;;;;;;;;;;;;;; (do ((fpg fpl (cdr fpg)) (fpids nil)) ((null fpg) (reverse fpids)) (do ((fpid (diana_get (car fpg) 'as_id_s) (cdr fpid)) (default (diana_get (car fpg) 'as_exp_void))) ((null fpid)) (ct_push (list (car fpid) default) fpids)))) ;;; finds the position of keyword parameter asp in formal list fpl + pp ;;;;;;;;;;; (defun find_formal(asp fpl pp) ;;;;;;;;;;; (*catch 'pos (let ((desig (diana_get asp 'as_designator))) (do ((afp fpl (cdr afp))) ((null afp) ;(break keyword-doesnt-match) (semgripe 'keyword_not_match_formal (implode (lowuplist (cadr desig)))) (*throw 'pos 0)) (cond ((param_matches asp (caar afp)) (*throw 'pos pp)) (t (%= pp (1+ *_*))))) ) )) ;;; Also finds the position of keyword parameter asp in formal list fpl + pp, ;;; but doesn't die when "keyword doesnt match formal"... ;;;;;;;;;;;; (defun find_formal2(asp fpl pp) ;;;;;;;;;;;; (let ((desig (diana_get asp 'as_designator))) (do ((afp fpl (cdr afp))) ((null afp) ;(break keyword-doesnt-match) (return 0)) (cond ((param_matches asp (caar afp)) (return pp)) (t (%= pp (1+ *_*))))))) ;;;;;;;;;;;;; (defun param_matches(x y) ; ++ should be made into a macro. ;;;;;;;;;;;;; (equal (diana_get x 'as_designator)(diana_get y 'lx_symrep)) ) ;;;;;;;;;;;; (defun sequence_kwp(lkwp fps pp gripe_p) ;;;;;;;;;;;; (do ((srtd nil) ; sorted keyword parameters. (kwps lkwp) ; actual keyword parameters remaining. (rfps fps (cdr rfps)) ; remaining formals. (fp pp) ;the first keyword. ) ((null rfps) (nreverse srtd)) (let ((np (assq pp kwps))) ; get next parameter. (cond ((null np) ; named parameter missing? (let ((np (n_th (- pp fp) fps))) ;(break default-param?) (cond ((second np) ;is there a default? (ct_push (diana_copy (second np)) srtd) (%= pp (1+ *_*)) (%= kwps (delq np kwps))) (t (%= pp (1+ *_*)) (ct_push nil srtd) (cond (gripe_p (semgripe 'missing_actual (implode (lowuplist (cadr (diana_get (first np) 'lx_symrep)))))) (t (*throw '*unmatched_keyword* nil))))))) (t (ct_push (diana_copy (diana_get (second np) 'as_actual)) srtd) (%= pp (1+ *_*)) (%= kwps (delq np kwps)))))) ) ;;;;;;; (defun copy_dn(dn) ;;;;;;; (cond ((null dn) nil) (t (cons (car dn)(copy_dn (cdr dn)))))) ;;;;;;;;;;; (defun find_needed(syn) ; find first 'wanted' thing from syntax. ;;;;;;;;;;; (cond ((get syn 'syntax_type) syn) ;;; (t (find_needed (third syn))) )) ;;;;;;; (defun sc_uop? (a) ;;;;;;; (memq a '(oper_plus oper_minus symb_abs symb_not))) ;;;;;;;;;;;;;;;;;;;;;;;; (defun eat_and_spit_thing_after (symb refvar) ;;;;;;;;;;;;;;;;;;;;;;;; (uci_let (rl (set refvar (find_cdr symb (eval refvar)))); delete leading dross (cond ((null rl) rl)(t (car rl))))) ;;;;;;;;;;;;;;;;;;;;;;; ;;;(defun sc_build_rel_op_rel_rep (exp) ;;;;;;;;;;;;;;;;;;;;;;; ;;; (cond ;;; ((null (cdadr exp)) (sc_build_binary_op exp)) ;;; (t (sc_build_binary_op `(,(car exp) (( ,(caadr exp) ;;; (sc_build_rel_op_rel_rep `(,(c****)))))))))) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun sc_build_seq_of_name_for_use (as) ;;;;;;;;;;;;;;;;;;;;;;;;;;;; (uci_let (firstname (caddr as) othernames (mapcar '(lambda(e) (cadr e)) (cadddr as))) (cons firstname othernames))) ;;;;;;;; (defun find_cdr (key lst) ;;;;;;;; (cond ((null lst) nil) ((eq (car lst) key) lst) (t (find key (cdr lst))))) (defun try_to_normalize() ;(break in-try_to_normalize) (let ((apn *awaiting_parameter_normalization*)) (setq *awaiting_parameter_normalization* nil) (mapc #'(lambda(call) (normalize_params call)) ;if so normalize it apn)) (let ((aan *awaiting_aggregate_normalization*)) (setq *awaiting_aggregate_normalization* nil) (mapc #'(lambda(agg) (normalize_aggregate agg)) ;if so normalize it aan)) (let ((defcons *awaiting_deferred_value*)) (setq *awaiting_deferred_value* nil) (mapc #'(lambda(const) ;(break look-at-deferredconst) nil) ;do later, defcons)) ) (defun with_library_units (lus);(break with_library_units ) (diana_put **current_block** (append (diana_get **current_block** 'ct_mixin_s) (mapcar #'(lambda(lu) (let* ((definition (diana_get lu 'sm_defn)) (embeddedcontext (and definition (diana_get definition 'ct_named_context))) (context (and embeddedcontext (diana_get embeddedcontext 'ct_is_enclosed_by)))) context)) lus)) 'ct_mixin_s))