;;; -*- mode:lisp;package:user;base:10.;fonts:(cptfontb) -*- ;;; $Header: /ct/interp/pser.l,v 1.55 85/06/21 12:30:56 bill Exp $ ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; pser.l ;;; ;;; Paul Robertson January 30, 1983 ;;; ;;; ;;; ;;; The C*T Ada Interpreters Parser Driver ;;; ;;; ;;; ;;; 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 'time)) ;Timing functions. (eval-when (compile load eval) (ct_load 'diana)) ;diana_nodes (eval-when (compile load eval) (ct_load 'sema)) ;sema functions and macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 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 -- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Internal Use Only Functions/Macros -- ;;; Prefix interpretation. ;;; pr_ Parser directives. ;;; sc_ Static Semantic Checker Directives. ;;; oper_ Operator and delimiter lexical symbols. ;;; symb_ Reserved words. (declare (special definlist synname first* start* *nonterminals* optional*)) ;;;;;;;; (defun clean_up () ;;;;;;;; (mapc #'(lambda (nt) (putprop nt nil 'first*list)) *nonterminals*)) ;;;;;;;;;;;;;;;;;;;;;;; (defun initialize_nonterminals() ;;;;;;;;;;;;;;;;;;;;;;; (clean_up) (mapc #'initialize_nonterminal *nonterminals*)) ;;; Gets rid of redundancies in a list (defun uniqueify (l) (map #'(lambda (x) (rplacd x (delete (car x) (cdr x)))) l)) ;;;;;;;;;;;;;;;;;;;;;; (defun initialize_nonterminal(nt) ;;;;;;;;;;;;;;;;;;;;;; (let ((first* (get nt 'firstlist)) (nononterms t)) (putprop nt (uniqueify (mapcan #'(lambda(tt) (let ((syntype (get tt 'syntax_type))) (ct_selectq syntype (non_terminal ;; check if it has a first*list-been done (let ((f*l (get tt 'first*list))) (cond (f*l (subst nil nil f*l)) (t (initialize_nonterminal tt) (subst nil nil (get tt 'first*list)))))) (terminal(list tt)) (otherwise (break) (format (terminal_output) "*** Don't know about ~A ***~%" nt))))) first*)) 'first*list))) #| ;;;;;;;;;;;;; (defun is_ada_syntax macro (l) ; hangs syntax onto property lists. ;;;;;;;;;;;;; `(progn 'compile (defprop ,(cadr l) ,(caddr l) ada_syntax) (defprop ,(cadr l) non_terminal syntax_type))) |# (eval-when (compile load eval) ;;;;;;;;;;;;;;;;; (defun create_definition (thing) ;;;;;;;;;;;;;;;;; (let ((fname (concat synname (gensym)))) (ct_push `(defun ,fname () ,(macroexpand thing)) definlist) `(function ,fname)))) (eval-when (compile load eval) ;;;;;;;;;;;;;; (defun def_ada_syntax macro (body) ;;;;;;;;;;;;;; (let* ((first* nil) (start* t) (definlist nil) (synname (cadr body)) (defbody (macroexpand (caddr body))) (bodyname (concat (cadr body) (gensym)))) (ct_push `(defun ,bodyname nil ,defbody) definlist) `(progn 'compile #|(declare (localf . ,(mapcan #'(lambda (d) (cond ((eq (cadr d) bodyname) nil) (t (list (cadr d))))) definlist)))|# ,@definlist (cond ((not (boundp '*nonterminals*))(setq *nonterminals* nil))) (ct_push ',(cadr body) *nonterminals*) (putprop ',(cadr body) ',first* 'firstlist) (putprop ',(cadr body) nil 'first*list) (putprop ',(cadr body) ',bodyname 'ada_syntax) (putprop ',(cadr body) 'non_terminal 'syntax_type))))) (eval-when (compile load eval) ;;;;; (defun pr_or macro (body) ;;;;; (let ((fname (concat synname (gensym))) ) (cond ((null (cadr body)) (setq fname nil)) ((atom (cadr body)) (setq fname `(function ,(cadr body)))) ; ((and (null (atom (cadr body))) (eq (caadr body) 'lambda)) (t ; Must be a lambda expression (setq definlist (cons `(defun ,fname ,(cadadr body) . ,(cddadr body)) definlist)) (setq fname `(function ,fname))) ; (t (setq fname (cadr body))) ) `(pr_or_aux ,fname . ,(mapcar '(lambda (x) (cond ((null x) (setq optional* t) nil) ((atom x) (cond (start* (ct_push x first*))) `',x) ((eq (car x) 'pr_or) (create_definition x)) ((eq (car x) 'pr_and) (create_definition x)) ((eq (car x) 'pr_and2) (create_definition x)) ((eq (car x) 'pr_and2c) (create_definition x)) ((eq (car x) 'pr_repeat) (create_definition x)) (t (cond ( (eq (car x) 'pr_restrict) (ct_push (third x) first*)) ( (memq (car x) '(pr_in_block pr_in_proc)) (ct_push (second x) first*))) (create_definition x)))) (cddr body))) ) ) ) (eval-when (compile load eval) ;;;;;; (defun pr_and macro (body) ;;;;;; (let* ((fname (concat synname (gensym))) (optional* nil) (start* start*) (ofirst* first*)) (do ((conj (cddr body)(cdr conj))) ((or (not conj) (and (not optional*) (not (eq first* ofirst*)))) (setq start* nil)) (setq optional* nil) (cond ((and start* (atom (car conj))) (setq start* nil) (ct_push (car conj) first*)) ((and start* (eq (caar conj) 'pr_restrict)) (ct_push (third (car conj)) first*) (setq start* nil)) ((and start* (memq (caar conj) '(pr_in_block pr_in_proc))) (ct_push (second (car conj)) first*) (setq start* nil)) (t (macroexpand (car conj))) )) (cond ((null (cadr body)) (setq fname nil)) ((atom (cadr body)) (setq fname `(function ,(cadr body)))) ; ((and (null (atom (cadr body))) (eq (caadr body) 'lambda)) (t ; Must be a lambda expression (setq definlist (cons `(defun ,fname ,(cadadr body) . ,(cddadr body)) definlist)) (setq fname `(function ,fname))) ; (t (setq fname (cadr body))) ) `(pr_and_aux ,fname . ,(mapcar '(lambda (x) (cond ((null x) nil) ((atom x) `',x) ((eq (car x) 'pr_or) (create_definition x)) ((eq (car x) 'pr_and) (create_definition x)) ((eq (car x) 'pr_and2) (create_definition x)) ((eq (car x) 'pr_and2c) (create_definition x)) ((eq (car x) 'pr_repeat) (create_definition x)) (t (create_definition x)))) (cddr body))) ) ) ) (eval-when (compile load eval) ;;;;;;; (defun pr_and2 macro (body) ;;;;;;; (let* ((fname (concat synname (gensym))) (start* start*) (ofirst* first*) (optional* nil)) (do ((conj (cddr body)(cdr conj))) ((or (not conj) (and (not optional*) (not (eq first* ofirst*)))) (setq start* nil)) (setq optional* nil) (cond ((and start* (atom (car conj))) (setq start* nil) (ct_push (car conj) first*)) ((and start* (eq (caar conj) 'pr_restrict)) (ct_push (third (car conj)) first*) (setq start* nil)) ((and start* (memq (caar conj) '(pr_in_block pr_in_proc))) (ct_push (second (car conj)) first*) (setq start* nil)) (t (macroexpand (car conj))) ) ) (cond ((null (cadr body)) (setq fname nil)) ((atom (cadr body)) (setq fname `(function ,(cadr body)))) ; ((and (null (atom (cadr body))) (eq (caadr body) 'lambda)) (t ; Must be a lambda expression (setq definlist (cons `(defun ,fname ,(cadadr body) . ,(cddadr body)) definlist)) (setq fname `(function ,fname))) ; (t (setq fname (cadr body))) ) `(pr_and2_aux ,fname . ,(mapcar '(lambda (x) (cond ((null x) nil) ((atom x) `',x) ((eq (car x) 'pr_or) (create_definition x)) ((eq (car x) 'pr_and) (create_definition x)) ((eq (car x) 'pr_and2) (create_definition x)) ((eq (car x) 'pr_repeat) (create_definition x)) (t (create_definition x)))) (cddr body))) ) ) ) (eval-when (compile load eval) ;;;;;;;; (defun pr_and2c macro (body) ;;;;;;;; (let* ((fname (concat synname (gensym))) (start* start*)) (cond ((and start* (atom (caddr body))) (setq start* nil) (ct_push (caddr body) first*)) (t (macroexpand (caddr body)) (setq start* nil))) (cond ((null (cadr body)) (setq fname nil)) ((atom (cadr body)) (setq fname `(function ,(cadr body)))) ; ((and (null (atom (cadr body))) (eq (caadr body) 'lambda)) (t ; Must be a lambda expression (setq definlist (cons `(defun ,fname ,(cadadr body) . ,(cddadr body)) definlist)) (setq fname `(function ,fname))) ; (t (setq fname (cadr body))) ) `(pr_and2c_aux ,fname . ,(mapcar '(lambda (x) (cond ((null x) nil) ((atom x) `',x) ((eq (car x) 'pr_or) (create_definition x)) ((eq (car x) 'pr_and) (create_definition x)) ((eq (car x) 'pr_and2) (create_definition x)) ((eq (car x) 'pr_and2c) (create_definition x)) ((eq (car x) 'pr_repeat) (create_definition x)) (t (create_definition x)))) (cddr body))) ) ) ) (eval-when (compile load eval) ;;;;;;;;; (defun pr_repeat macro (body) ;;;;;;;;; (let* ((fname (concat synname (gensym)))) (cond ((null (cadr body)) (setq fname nil)) ((atom (cadr body)) (setq fname `(function ,(cadr body)))) ; ((and (null (atom (cadr body))) (eq (caadr body) 'lambda)) (t ; Must be a lambda expression (setq definlist (cons `(defun ,fname ,(cadadr body) . ,(cddadr body)) definlist)) (setq fname `(function ,fname))) ; (t (setq fname (cadr body))) ) (setq optional* t) `(pr_repeat_aux ,fname . ,(mapcar '(lambda (x) (cond ((null x) nil) ((atom x) (cond (start* (ct_push x first*))) `',x) ((eq (car x) 'pr_or) (create_definition x)) ((eq (car x) 'pr_and) (create_definition x)) ((eq (car x) 'pr_and2) (create_definition x)) ((eq (car x) 'pr_and2c) (create_definition x)) ((eq (car x) 'pr_repeat) (create_definition x)) (t (cond ( (eq (car x) 'pr_restrict) (ct_push (third x) first*)) ( (memq (car x) '(pr_in_block pr_in_proc)) (ct_push (second x) first*))) (create_definition x)))) (cddr body))) ) ) ) ;;; Returns true if arg has a property list. All atoms have property lists. ;;; otherwise disembodied property lists must have null car. ;;; (defun pl?(u)(or (atom u)(null (car u)))) ;;; ;;; The parser driver. ;;;;;;; (defun parserd(syntaxspec) ; parse from node syntaxspec. ;;;;;;; (let ( (result (cond ((symbolp syntaxspec) ; (ct_princ syntaxspec)(ct_princ "?")(ct_terpri) (let ((sy_net (get syntaxspec 'ada_syntax)) (res nil) (type (get syntaxspec 'syntax_type))) (cond ((eq type 'terminal) ; expect this token from the lana. (cond ((or (eq la_current_symbol syntaxspec) (and (consp la_current_symbol) (eq (car la_current_symbol) syntaxspec))) (prog1 la_current_symbol ; return this symbol. (la_lex))) ; eat the symbol. )) ((and (eq type 'non_terminal) (prog2 (ct_push syntaxspec *current_non_terminal*) (cond ((and (memq (cond ((atom la_current_symbol) la_current_symbol) (t (car la_current_symbol))) (get syntaxspec 'first*list)) (eq (*catch 'embedded_error (setq res (funcall sy_net))) 'embedded_error) ) (let ((error_proc (get syntaxspec 'embedded_error))) (cond ((null error_proc) (gripe `(error in ,syntaxspec))) (t (funcall error_proc)))) (setq res 'nulconj)) (t res)) (ct_pop *current_non_terminal*))) ; recursively invoke parser if its a ; non-terminal. res) ((null type) (setq res (funcall syntaxspec)))))) (t (funcall syntaxspec))))) (cond ((and *debugparser* result (symbolp syntaxspec)) (ct_format t "Parsed ~A~&" syntaxspec)) ) result ) ) ;;; Parses a conjunctive production. Conjunctions are parsed left to right and ;;; result in a syntax tree reversed in order of parsing. If the first ;;; conjunctive fails, nil is returned, failure of later conjunctions gives ;;; rise to a gripe. Resulting syntax tree is reversed before returning so as ;;; to recover original order. ;;; The parameters to pr_and are code and a list of conjunctions. After the ;;; conjunction has been assembled, code is run over it, If code is nil, the ;;; assembled conjunction is returned unchanged. ;;;;;;;;;; (defun pr_and_aux (&rest conjlist) ; parse sequential conjunction. ;;;;;;;;;; (do ((cl (cdr conjlist) (cdr cl)) ; incrementally parse it. (*preparsecc* *pcharcount*) ; cc before parse. (*postparsecc* 0) ; with preparsecc defines region. (*srcposbeg* la_psrcpos) (*linposbeg* la_plinpos) (code (car conjlist)) (committed nil) ; after first match must proceed. (ress nil) (semerr nil nil) (*syntree* nil)) ; result of parse. ((null cl) (cond ((consp *syntree*)(setq *syntree* (reverse *syntree*)))) (let ((conjres (cond ((null code) *syntree*) (t (funcall code *syntree*))))) (cond ((null conjres) 'nulconj) ((eq conjres 'fail) nil) (t conjres)))) (cond ((setq ress (parserd (car cl) )) (setq *postparsecc* *pcharcount*) (setq *syntree* (cond ((eq ress t) *syntree*) ((memq ress '(trivdisj norepeats nulconj)) (cons nil *syntree*)) ;retain order of and. (t (cons ress *syntree*)))) (setq committed (null (memq ress '(t trivdisj norepeats nulconj))))) ;; We are committed if we get success. ;; trivial success not counted! (committed (if *debugparser* (gripe `(,(format nil "A ~a was expected in a ~a." (car cl) *current_non_terminal*)))) (let ((error_recovery (cond ((atom (find_needed (car cl))) (get (find_needed (car cl)) 'error_missing)) (t nil)))) ;What do we do if there is an error? (cond ((null error_recovery) (gripe `(,(format nil "A ~a was expected." (find_needed (car cl)))))) (t (funcall error_recovery)))) (cond ((and (null *syntree*)(null (cdr cl)))(setq *syntree* 'nulconj)) (t (ct_push nil *syntree*)) ; ?? cud.b.dangerus ) ) (t (return nil)) ; Return nil. Not this production. ) ) ) ;;;ll(2) version of pr_and, same format as pr_and. Additional restriction is that ;;;the first two syntactic entries must consist of exactly one symbol. ;;;;;;;;;;; (defun pr_and2_aux (&rest conjlist) ; parse sequential conjunction. ;;;;;;;;;;; (let ((previous_symbol la_current_symbol)) (cond ((parserd (second conjlist) ) (let ((this_symbol la_current_symbol)) (cond ((parserd (third conjlist)) (putback_symbol this_symbol) (putback_symbol previous_symbol) (apply (function pr_and_aux) conjlist)) (t (putback_symbol previous_symbol) nil)))) (t nil)))) ;;;ll(2) version of pr_and, same format as pr_and. Additional restriction is that ;;;The first entry is a symbol, and the second is a symbol ;;;that will be unread after being found, so that it must be repeated in the ;;;third etc.. ;;;;;;;;;;;; (defun pr_and2c_aux (&rest conjlist) ; parse sequential conjunction. ;;;;;;;;;;;; (let ((previous_symbol la_current_symbol)) (cond ((parserd (second conjlist) ) ;does the first symbol match? (let ((this_symbol la_current_symbol)) (cond ((parserd (third conjlist)) ;does the second match? (putback_symbol this_symbol) ;yes, put back both parts (putback_symbol previous_symbol) (apply (function pr_and_aux) ;try real thing! (cons (first conjlist) (cdddr conjlist)))) (t (putback_symbol previous_symbol) nil)))) (t nil)))) ;failed on first symbol. ;;; Parses up a list of zero or more components of type syntaxtype. Always ;;; succeeds. Resultant parse tree is in reverse order of parsing. ;;; Result is reversed to recover original order. ;;; Two arguments to pr_repeat, are code and syntaxspec, the former should be ;;; a lambda expression of one variable which will transform the produced ;;; piece of syntax. nil implies no transformation is required. The ;;; transformation function MUST NOT return a nil value. ;;;;;;;;;;;;; (defun pr_repeat_aux (&rest syntaxspec) ;;;;;;;;;;;;; (do ((*syntree* nil) ; accumulate repetitions. (*preparsecc* *pcharcount*) (*postparsecc* 0) (*srcposbeg* la_psrcpos) (*linposbeg* la_plinpos) (success (parserd (cadr syntaxspec) ) (parserd (cadr syntaxspec) ))) ((null success) (%= *postparsecc* *pcharcount*) (cond (*syntree* (cond ((null (car syntaxspec))(reverse *syntree*)) (t (apply (car syntaxspec) (list (reverse *syntree*)))))) (t 'norepeats))) (cond ((null (eq success t))(setq *syntree* (cons success *syntree*)))))) ;;; Parses a disjunctive production. A disjunctive containing nil always ;;; succeeds. Disjunctions are tried in the order presented, the first ;;; successful parse results in a successful return. ;;;;;;;;; (defun pr_or_aux (&rest disjlist) ; Parse disjunction, nil always succeeds. ;;;;;;;;; (let ((old_committment committed)) (let ((choices (cdr disjlist)) ;the acceptable choices. (code (car disjlist))) ;nil or a possible way out!!(error handler). (do ((dl choices (cdr dl)) ; Search for first successful match. (*syntree* nil)) ; non-nil if succeeds. ((or *syntree* (null dl)) (cond (*syntree*) (code (funcall code)))) (setq committed (and (null (cdr dl)) old_committment)) ; only the last entry can ; inherit commitment. (setq *syntree* (cond ((null (car dl)) 'trivdisj) (t (parserd (car dl) )))))))) ;;;; (defun dpl?(l)(and (consp l)(consp (cdr l))(null (cadr l)))) ;;;; ;;;;;;;;; (defun conj_part(n) ;;;;;;;;; (n_th (- (1+ (length *syntree*)) n) *syntree*)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; 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. ;;;;;;;;;;;;; (defun diana_pointer(v) ; diana lists are terminated by voids, not ;;;;;;;;;;;;; ; nils (cond ((null v)(sc_diana dn_void lx_comments '("generated"))) (t v))) ;;; Build a function call node. handles infix operators. Expects a list of the ;;; general form (dnode ((operator dnode) (operator dnode) ..)) ;;; generates a function call tree for the above. (left associative). (eval-when (compile load eval) (def_record_type infix_call infix (leftleaf rightsubtree)) (def_record_type subtree nil (operator rightleaf)) ) (declare (special foo)) ;;;;;;;;;;;;;;;;;;; (defun sc_function_call_op () ; build function_call node ;;;;;;;;;;;;;;;;;;; (cond ((memq (subtree%operator (first (infix_call%rightsubtree *abstract_syntax*))) '(symb_and_then symb_or_else)) (let ((right (cond ((cdr (infix_call%rightsubtree *abstract_syntax*)) (let ((*abstract_syntax* (infix_call (cadar (infix_call%rightsubtree *abstract_syntax*)) (cdr (infix_call%rightsubtree *abstract_syntax*))))) (sc_function_call_op))) (t (cadar (infix_call%rightsubtree *abstract_syntax*)))))) (sc_diana dn_binary as_exp1 (infix_call%leftleaf *abstract_syntax*) as_exp2 right as_binary_op (cond ((eq (subtree%operator (first (infix_call%rightsubtree *abstract_syntax*))) 'symb_and_then) (sc_diana dn_and_then)) (t (sc_diana dn_or_else)))))) (t (prog (foo) ; what a crock!!! (return (let ((firstcall ; The first function call (perhaps only) (normalize_params (dissambiguate_function_reference (sc_diana dn_function_call lx_prefix nil ; this was an infix operator. as_name nil as_param_assoc_s (sc_diana dn_param_assoc_s as_list (let ((rst (subtree%rightleaf (first (infix_call%rightsubtree *abstract_syntax*))))) (cond (rst (list (infix_call%leftleaf *abstract_syntax*) rst)) (t (list (infix_call%leftleaf *abstract_syntax*)))))) tp_vfuns (ada_declared `(lex_ident ,(cadr (op_name (subtree%operator (first (infix_call%rightsubtree *abstract_syntax*)))))) nil 'function t))))) (restcalls ;; remaining subtree - elaborated recursively. (cdr (infix_call%rightsubtree *abstract_syntax*)))) (cond (restcalls (setq *abstract_syntax* (infix_call firstcall restcalls)) (sc_function_call_op)) (t firstcall)))))))) ;;;;;;; (defun op_name (intnam) ;;;;;;; (ct_selectq intnam (oper_lt '(lex_string (#/<))) (oper_gt '(lex_string (#/>))) (oper_plus '(lex_string (#/+))) (oper_minus '(lex_string (#/-))) (oper_star '(lex_string (#/*))) (oper_slash '(lex_string (#//))) (oper_starstar '(lex_string (#/* #/*))) (oper_le '(lex_string (#/< #/=))) (oper_ge '(lex_string (#/> #/=))) (oper_equals '(lex_string (#/=))) (oper_notequals '(lex_string (#// #/=))) (oper_ampersand '(lex_string (#/&))) (symb_mod '(lex_string (#/m #/o #/d))) (symb_abs '(lex_string (#/a #/b #/s))) (symb_rem '(lex_string (#/r #/e #/m))) (symb_not '(lex_string (#/n #/o #/t))) (symb_and '(lex_string (#/a #/n #/d))) (symb_or '(lex_string (#/o #/r ))) (symb_xor '(lex_string (#/x #/o #/r))) ; (t (break)))) ; (otherwise (lose 'ct_uko 'op_name)))) ;;;;;;;;;;;;; (defun operator_name(lextoken) ; converts lexical token into a name. ;;;;;;;;;;;;; `(lex_operator ,(cdddddr (exploden lextoken)))) ;;;;;;;;;;;;;;;; (defun sc_function_call (*abstract_syntax*); this is a terrible crock that ;;;;;;;;;;;;;;;; (sc_function_call_op)) ;MUST be deleted asap!!!!!! ;;;;;;;;;;;;;;;;;; (defun find_selected_name (dn) ;;;;;;;;;;;;;;;;;; (cond ((null dn) nil) ((consp dn)(find_selected_name (car dn))) (t (ct_selectq (diana_nodetype_get dn) (dn_selected (find_selected_name (diana_get dn 'as_designator_char))) (otherwise (diana_get dn 'lx_symrep)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun complain_about_awaiting_disambiguation() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (mapc #'dissambiguate_function_reference *awaiting_disambiguation*) (mapc #'(lambda(dn) (semgripe 'ambig_subprog_ref (let* ((tpvfuns (first (diana_get dn 'tp_vfuns))) (lxsr (and tpvfuns (find_selected_name tpvfuns)))) (implode (cadr lxsr))) (source_region%linstart (diana_get dn 'lx_srcpos))) (%= *awaiting_parameter_normalization* (delq dn *_*))) *awaiting_disambiguation*)) (declare (special *class_restriction* *no_function*)) ;;;;;;;;;;; (defun no_function fexpr (syntactic_unit) ;;;;;;;;;;; (let* ((*no_function* t) (*class_restriction* '(object formal_parameter number constant package pragma_parameter generic_unit library_unit task procedure entry)) (parsed (parserd (car syntactic_unit)))) parsed)) ;;; Checks that the identifier exists and has the correct CLASS. A semantic ;;; error results if the identifier either doesn't exist (hasn't appeared in ;;; a declaration) or has an incompatible CLASS such as being a type when a ;;; task was expected. Note that CLASS is used here to mean a broad taxonomy ;;; of identifier such as tasks types packages etc. Ada types provide a more ;;; detailed categorization. ;;;;;;;;;;; (defun pr_restrict fexpr (object) ; (pr_restrict class syntactic_unit) ;;;;;;;;;;; ;;used by ada_declared-for name. (cond ((and *no_function* (eq (car object) 'function)) nil) (t (let ((*class_restriction* (car object))) (let ((parsed (parserd (cadr object)))) (cond (parsed ; if we parsed the object, ;lets see if its ; class is ok. (cond ; object may be an id a ;lex_ident or other ((and (not (diana_nodep parsed)) (memq (car parsed) '(lex_ident lex_string))) ; The parsed object is an identifier, ; find_name should yield its declaration ; which must have CLASS (car object). (let ((defs (walk_env_rec (get_id `(lex_ident ,(cadr parsed)) (la_hash (cadr parsed))) **current_block** nil))) (cond ((memq (car object) (mapcar (function (lambda (symboltableentry) (la_id%class symboltableentry))) defs)) `(lex_ident ,(cadr parsed))) ; class matched OK. ((not committed) (putback_symbol parsed) ; symbol didnt match, ; put it back so that ; a future match can ; be attempted. nil) ; report failure for this one. (t (semgripe 'obj_expected (car object)) (sc_diana dn_used_name_id sm_defn #|(sc_diana dn_semantic_error sm_wegot parsed)|# nil)) ))) ((and (diana_nodep parsed) (memq 'lx_symrep (diana_actual_attributes parsed))) ;; (diana_get parsed 'lx_symrep)) ; if it is a diana node with ;a symrep slot ; lookup that slot in the ;symbol table and ; check its type. (cond ((memq (car object) (mapcar (function (lambda (symboltableentry) (la_id%class symboltableentry))) (get_id (diana_get parsed 'lx_symrep) (la_hash (cadr (diana_get parsed 'lx_symrep)))))) parsed) ; class matched OK. ; later we will want ; to add the back ; pointer to the ; definition for this ; case. ((not committed) (putback_symbol parsed); symbol didnt match, ; put it back so that ; a future match can ; be attempted. nil) ; report failure for this one. (t (semgripe 'obj_expected (car object)) (sc_diana dn_used_name_id sm_defn #|(sc_diana dn_semantic_error sm_wegot parsed)|# nil)) )) (t parsed))))))))) ;;; predicate that determines if a diana node is a subprogram call. ;;;;;;;;;;;;;;;;;;;;;; (defun subprogram_call_node_p(dn); returns t if dn is a subprogram diana node. ;;;;;;;;;;;;;;;;;;;;;; (and (diana_nodep dn) (memq (diana_nodetype_get dn) '(dn_procedure_call dn_function_call)))) ;;;;;;;;;;;;; (defun find_selected(dn) ;;;;;;;;;;;;; (cond ((null dn) nil) ((eq (diana_nodetype_get dn) 'dn_selected) (find_selected (diana_get dn 'as_designator_char))) ((eq (diana_nodetype_get dn) 'dn_used_name_id) dn) ((eq (diana_nodetype_get dn) 'dn_generic_id) (sc_diana dn_used_name_id sm_defn dn)) ((eq (diana_nodetype_get dn) 'dn_proc_id) (sc_diana dn_used_name_id sm_defn dn)) ((eq (diana_nodetype_get dn) 'dn_procedure_call) (find_selected (car (diana_get dn 'tp_vfuns)))) ((eq (diana_nodetype_get dn) 'dn_function_call) (find_selected (car (diana_get dn 'tp_vfuns)))) ((eq (diana_nodetype_get dn) 'dn_entry_id) dn) ((eq (diana_nodetype_get dn) 'dn_function_id) (sc_diana dn_used_name_id sm_defn dn)) ((and (consp dn)(= (length dn) 1)) (find_selected (car dn))) (t (lose 'fe_edn 'find_selected )))) ;;; Get the definition of the name (if it is a name) ;;;;;;;;;; (defun strip_name(name) ;;;;;;;;;; (cond ((null name) nil) ((eq (diana_nodetype_get name) 'dn_used_name_id) (strip_name (diana_get name 'sm_defn))) (t name))) ;;;;;;;;;;;;;;; (defun pairify_formals (formals) ;;;;;;;;;;;;;;; (mapcan #'(lambda(id) (list `(,(diana_get id 'lx_symrep) ,(diana_get id 'sm_obj_type)))) (mapcan #'(lambda(fg) (#+franz copy_dn #+lispm copylist (diana_get fg 'as_id_s))) formals))) ;;;;;;;; (defun last_car(l) ;;;;;;;; (cond ((null (cdr l))(car l)) (t (last_car (cdr l))))) ;;;;;;;;; (defun find_defo(ids) ;;;;;;;;; (let ((sm_first (mapcan #'(lambda(id) (let ((defined_in (diana_get id 'ct_st_defining_block))) (cond ((null defined_in) (semgripe 'no_def_block (implode (cadr (diana_get id 'lx_symrep))))) ((or t ; need to find local context++ (eq defined_in **current_block**);either defined here. (memq defined_in (diana_get **current_block** 'ct_mixin_s)));or there (list id))))) ids))) (cond ((> (length sm_first) 1) (semgripe 'mult_def_occur) nil) (t (cond ((null sm_first) nil) #| ((diana_get (car sm_first) 'sm_first) (diana_get (car sm_first) 'sm_first))|# (t (car sm_first))))))) ;;; eof ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;