;;; -*- mode:lisp;package:user;base:10.;fonts:(cptfontb) -*- ;;; $Header: /ct/interp/adas60.l,v 1.41 84/10/10 19:11:08 penny Exp $ ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; adas60.l ;;; ;;; Paul Robertson January 30, 1983 ;;; ;;; ;;; ;;; The C*T Ada Interpreters Syntax and Static Semantics ;;; ;;; ;;; ;;; 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 'stdenv)) ; contains vital macro (eval-when (compile load eval) (ct_load 'sema)) ; contains vital MACRO (eval-when (compile load eval) (ct_load 'pser)) ; contains vital MACRO ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 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. ;;;-- 5. Statements ;;;-- ============== ;;;-- 5.1 Simple and Compound Statements, Sequences of Statements ;;; ;;;-- Syntax 5.1.A ;;;-- sequence_of_statements ::= statement {statement} ;;;-- ;;; ;;; ;;; STM_S ::= stm_s; ;;; ;;; stm_s => as_list : Seq Of STM; ;;; stm_s => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;; (defun last_label (as) ;;;;;;;;;; (do ((frob as (cdr frob)) (ll nil)) ((null frob) ll) (cond ((eq (diana_nodetype_get (car frob)) 'dn_labeled) (setq ll (car frob)) (diana_put (diana_get ll 'as_id) (cadr frob) 'as_stm) (diana_put (diana_get ll 'as_id) (car as) 'ct_labeled) (diana_put ll (cadr frob) 'as_stm))))) ;;;;;;;;;;;;;;;;;;;;;; (def_ada_syntax sequence_of_statements ;;;;;;;;;;;;;;;;;;;;;; (pr_and (lambda(as) ;;first is the labeled's.. chain them up if more than one. (let ((lastlab (last_label (first as)))) (cond ((and (diana_nodep lastlab) (eq (diana_nodetype_get lastlab) 'dn_labeled)) (diana_put (diana_get lastlab 'as_id) (second as) 'as_stm) (diana_put lastlab (second as) 'as_stm)) ) (sc_diana dn_stm_s as_list (append (cond (lastlab (list (car (first as)))) ((first as) (append (first as) (list (second as)))) (t (list (second as)))) (cond ((third as) (diana_get (third as) 'as_list))))))) (pr_repeat nil (pr_or nil (pr_and (lambda(as) (sc_diana dn_labeled as_id (add_name (second as) 'label (let ((lid (sc_diana dn_label_id lx_symrep (second as) sm_stm nil ; gets filled in later. ))) (diana_put lid lid 'sm_defn) lid) nil) as_stm nil ; gets filled in later ) ) oper_mlt lex_ident oper_mgt) pragma)) (pr_or nil ; this is an ll(2) part of the grammar. ; first check for a named block or loop. (pr_and2c (lambda(as) (popcontext) (cond ((null (fourth as)) (semgripe 'missing_matching_mandatory_name (implode (lowuplist (cadr (diana_get (first as) 'lx_symrep))))))) (matching_ident (diana_get (first as) 'lx_symrep) (fourth as)) ;idents must match. (diana_put (first as) (third as) 'sm_stm) (sc_diana dn_named_stm as_id (first as) as_stm (third as))) lex_ident oper_colon ;ll2 symnbols (pr_and (lambda (as) (pushcontext) ;make sure not visible outside loop or block (let ((lid (add_name (first as) 'named (sc_diana dn_named_stm_id lx_symrep (first as) sm_stm nil; gets put in later ct_named_context nil);gets put in later nil))) (rplaca *named_stm_stack* lid) (diana_put lid lid 'sm_defn) lid)) lex_ident) oper_colon (pr_or nil loop_statement block_stmt) lex_ident ;idents must match. oper_semicolon) (pr_and (lambda(as) (progn (cond ((subprogram_call_node_p (second as)) (diana_put (second as) (mapcan #'(lambda (cand) (cond ((eq (diana_nodetype_get cand) 'dn_function_call) nil) (t (list cand)))) (find_name (first as) '(procedure entry) t)) 'tp_vfuns)) ((second as) (diana_put (second as) (find_name (first as) nil) 'as_name))) (cond ((subprogram_call_node_p (second as)) (let ((void (sc_diana dn_void))) (diana_put (second as) (diana_get void 'lx_srcpos) 'lx_srcpos) (normalize_params (dissambiguate_function_reference (second as))))) ((and (second as) (eq (diana_nodetype_get (second as)) 'dn_assign)) (let ((void (sc_diana dn_void))) (diana_put (second as) (diana_get void 'lx_srcpos) 'lx_srcpos)) (cond ((not (assignable_p (diana_get (second as) 'as_name))) (semgripe 'lhs_not_assignable));ERRMSG ((not (assignment_compatible (diana_get (second as) 'as_exp) (diana_get (second as) 'as_name))) (semgripe 'types_not_assignable))))) (second as))) ; deposit the name. (pr_and (lambda(as) (cond ((name_declared_check (first as)) (first as)))) (pr_or nil (pr_and (lambda (as) (second as)) (pr_and (lambda (as) (let* ((symstk (do ((stk nil)) ((memq la_current_symbol '(oper_semicolon oper_assign)) stk) (ct_push la_current_symbol stk) (la_lex))) (funcall_p (eq la_current_symbol 'oper_assign))) (mapc #'putback_symbol symstk) (putback_symbol (first as)) (cond ((not funcall_p) 'fail)))) lex_ident) name) (no_function name))) ; either proc.call,assignment or attribute. (pr_or nil (pr_and (lambda(as) (sc_diana dn_assign as_exp (second as) as_name nil ; Gets filled in later. ) ) (pr_or fortran_assignment_check oper_assign) expression oper_semicolon) (pr_and (lambda(as) (sc_diana dn_code as_exp (second as) as_name nil ; gets filled in later. ) ) oper_quote general_aggregate ; (pr_restrict agg_or_exp general_aggregate) oper_semicolon) procedure_or_entry_call)) (pr_and car loop_statement oper_semicolon) (pr_and car block_stmt oper_semicolon) (pr_and (lambda(as) (sc_diana dn_null_stm ) ) symb_null oper_semicolon) exit_statement return_statement goto_statement delay_statement delay_statement abort_statement raise_statement if_statement case_statement accept_statement select_statement) (pr_or nil sequence_of_statements nil))) ;;;-- 5.3 If Statements ;;; ;;;-- Syntax 5.3.A ;;;-- if_statement ::= ;;;-- 'if' condition 'then' ;;;-- sequence_of_statements ;;;-- {'elsif' condition 'then' ;;;-- sequence_of_statements} ;;;-- ['else' ;;;-- sequence_of_statements] ;;;-- 'end' 'if' ';' ;;;-- ;;; ;;; ;;; STM ::= if; ;;; ;;; if => as_list : Seq Of COND_CLAUSE; ;;; if => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; COND_CLAUSE ::= cond_clause; ;;; ;;; cond_clause => as_exp_void : EXP_VOID, ;;; as_stm_s : STM_S; ;;; cond_clause => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;-- Syntax 5.3.B ;;;-- condition ::= expression ;;;-- ;;; ;;; ;;; -- condition is replaced by EXP ;;; ;;;;;;;;;;;; (def_ada_syntax if_statement ;;;;;;;;;;;; (pr_and (lambda(as) (sc_diana dn_if as_list (append (cons (first as)(second as)) (third as)))) (pr_and (lambda(as) (cond ((not (boolean_expression_p (second as))) (semgripe 'not_bool_exp))) (sc_diana dn_cond_clause as_exp_void (second as) as_stm_s (fourth as))) symb_if expression (pr_and (lambda (as) (pushcontext) (first as)) symb_then) (pr_and (lambda (as) (popcontext) (first as)) sequence_of_statements)) (pr_or nil (pr_repeat nil (pr_and (lambda(as) (cond ((not (boolean_expression_p (second as))) (semgripe 'not_bool_exp))) (sc_diana dn_cond_clause as_exp_void (second as) as_stm_s (fourth as))) symb_elsif expression (pr_and (lambda (as) (pushcontext) (first as)) symb_then) (pr_and (lambda (as) (popcontext) (first as)) sequence_of_statements))) nil) (pr_or nil (pr_and (lambda(as) (list (sc_diana dn_cond_clause as_exp_void (sc_diana dn_void) as_stm_s (second as)))) (pr_and (lambda (as) (pushcontext) (first as)) symb_else) (pr_and (lambda (as) (popcontext) (first as)) sequence_of_statements)) nil) symb_end symb_if oper_semicolon)) ;;;-- 5.4 Case Statements ;;; ;;;-- Syntax 5.4 ;;;-- case_statement ::= ;;;-- 'case' expression 'is' alternative {alternative} ;;;-- 'end' 'case' ';' ;;;-- alternative ::= 'when' choice {'|' choice} '=>' sequence_of_statements ;;;-- ;;; ;;; ;;; STM ::= case; ;;; ALTERNATIVE_S ::= alternative_s; ;;; ALTERNATIVE ::= alternative | pragma; -- pragma allowed before ;;; -- 'when' ;;; ;;; case => as_exp : EXP, ;;; as_alternative_s : ALTERNATIVE_S; ;;; case => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; alternative_s => as_list : Seq Of ALTERNATIVE; ;;; alternative_s => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; alternative => as_choice_s : CHOICE_S, ;;; as_stm_s : STM_S; ;;; alternative => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;;;;;; (def_ada_syntax case_statement ;;;;;;;;;;;;;; (pr_and (lambda(as) (sc_diana dn_case as_exp (second as) as_alternative_s (sc_diana dn_alternative_s as_list (fourth as)))) symb_case expression symb_is case_statement_naka ; returns a Seq of alternative symb_end symb_case oper_semicolon)) ;;;;;;;;;;;;;;;;;;; (def_ada_syntax case_statement_naka ;;;;;;;;;;;;;;;;;;; (pr_and cadr symb_when (pr_or nil (pr_and (lambda(as) (list (sc_diana dn_alternative as_choice_s (sc_diana dn_choice_s as_list (list (sc_diana dn_others))) as_stm_s (third as)))) symb_others (pr_and (lambda (as) (pushcontext) (first as)) oper_goes) (pr_and (lambda (as) (popcontext) (first as)) sequence_of_statements)) (pr_and (lambda(as) (cons (sc_diana dn_alternative as_choice_s (sc_diana dn_choice_s as_list (cons (first as)(second as))) as_stm_s (fourth as)) (fifth as))) choice_range (pr_repeat nil (pr_and cadr oper_bar choice_range)) (pr_and (lambda (as) (pushcontext) (first as)) oper_goes) (pr_and (lambda (as) (popcontext) (first as)) sequence_of_statements) (pr_or nil case_statement_naka nil))))) ;;;-- 5.5 Loop Statements ;;; ;;;-- Syntax 5.5.A ;;;-- loop_statement ::= ;;;-- [identifier ':'] [iteration_clause] basic_loop ;;;-- [identifier] ';' ;;;-- ;;; ;;; ;;; STM ::= named_stm; ;;; ;;; named_stm => as_id : ID, -- always a 'label_id' ;;; as_stm : STM; -- 'loop' or 'block' ;;; named_stm => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;-- Syntax 5.5.B ;;;-- basic_loop ::= ;;;-- 'loop' ;;;-- sequence_of_statements ;;;-- 'end' 'loop' ;;;-- ;;; ;;; ;;; STM ::= LOOP; ;;; LOOP ::= loop; ;;; ITERATION ::= void; ;;; ;;; loop => as_iteration : ITERATION, ;;; as_stm_s : STM_S; ;;; loop => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;-- Syntax 5.5.C ;;;-- iteration_clause ::= ;;;-- 'for' loop_parameter 'in' ['reverse'] discrete_range ;;;-- | 'while' condition ;;;-- loop_parameter ::= identifier ;;;-- ;;; ;;; ;;; ITERATION ::= for | reverse; ;;; ;;; for => as_id : ID, -- always an 'iteration_id' ;;; as_dscrt_range : DSCRT_RANGE; ;;; for => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; reverse => as_id : ID, -- always an 'iteration_id' ;;; as_dscrt_range : DSCRT_RANGE; ;;; reverse => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; ;;; DEF_ID ::= iteration_id; ;;; ;;; iteration_id => lx_srcpos : source_position, ;;; lx_comments : comments, ;;; lx_symrep : symbol_rep; ;;; iteration_id => sm_obj_type : TYPE_SPEC; ;;; ;;; ;;; ITERATION ::= while; ;;; ;;; while => as_exp : EXP; ;;; while => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;;;;;; (def_ada_syntax loop_statement ;;;;;;;;;;;;;; (pr_and (lambda(as) (ct_pop *named_stm_stack*) (cond ((null (first as))) (t (popcontext))) (sc_diana dn_loop as_iteration (cond ((null (first as)) (sc_diana dn_void)) (t (first as))) as_stm_s (third as))) (pr_or nil (pr_and (lambda(as) (pushcontext) ; make while loop a block. (cond ((not (boolean_expression_p (second as))) (semgripe 'not_bool_exp))) (sc_diana dn_while as_exp (second as))) symb_while expression) (pr_and (lambda(as) (pushcontext) ; make for loop a block. (let ((loop_id (add_name (second as) 'object ; should distinguish iterations so ; that we can check for asignments.?? (let ((itid (sc_diana dn_iteration_id lx_symrep (second as) sm_obj_type nil))) ; not known yet. (diana_put itid itid 'sm_defn) ;is its own definition. itid) nil))) (cond ((car *named_stm_stack*) (diana_put (car *named_stm_stack*) **current_block** 'ct_named_context))) (diana_put loop_id (extract_basetype (fifth as)) ;better check this++ 'sm_obj_type) (cond ((null (fourth as)) (sc_diana dn_for as_id loop_id as_dscrt_range (fifth as))) (t (sc_diana dn_reverse as_id loop_id as_dscrt_range (fifth as)))))) symb_for lex_ident symb_in (pr_or nil symb_reverse nil) index_range) nil) (pr_and (lambda (as) (pushcontext) (ct_push nil *named_stm_stack*) (first as)) symb_loop) (pr_and (lambda (as) (popcontext) (first as)) sequence_of_statements) symb_end symb_loop)) ;;;-- 5.6 Blocks ;;; ;;;-- Syntax 5.6 ;;;-- block ::= ;;;-- [identifier ':'] ;;;-- ['declare' ;;;-- declarative_part] ;;;-- 'begin' ;;;-- sequence_of_statements ;;;-- ['exception' ;;;-- exception_handler {exception_handler}] ;;;-- 'end' [identifier] ';' ;;;-- ;;; ;;; ;;; STM ::= block; ;;; -- see 5.5.A for named block ;;; ;;; block => as_item_s : ITEM_S, ;;; as_stm_s : STM_S, ;;; as_alternative_s : ALTERNATIVE_S; ;;; block => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;; (def_ada_syntax block_stmt ;;;;;;;;;; (pr_and (lambda(as) ;(break in-block-statement) (cond ((first as)(popcontext))) (sc_diana dn_block as_item_s (second (first as)) as_stm_s (first (second as)) as_alternative_s (second (second as)))) (pr_or nil (pr_and nil (pr_and (lambda(as) (pushcontext) (cond ((car *named_stm_stack*) (diana_put (car *named_stm_stack*) **current_block** 'ct_named_context))) (first as)) symb_declare) (pr_or nil declarative_part nil)) nil) statement_part)) ; returns a list (sequence_of_statements exception) ;;;;;;;;;;;;;; (def_ada_syntax statement_part ;;;;;;;;;;;;;; (pr_and (lambda(as) (ct_pop *named_stm_stack*) (cond ((null (third as))(list (second as) nil)) (t (list (second as)(third as))))) (pr_and (lambda (as) (ct_push nil *exception_handler_stack* ) (ct_push nil *named_stm_stack*) (first as)) symb_begin) sequence_of_statements (pr_or nil (pr_and cadr (pr_and (lambda (as) (rplaca *exception_handler_stack* t) (first as)) symb_exception) exception_part) (pr_and cadr (pr_and (lambda(as) (rplaca *exception_handler_stack* t) (putback_symbol (first as)) (gripe '("The reserved word 'exception' was expected.") '((lrmref "LRM" (lrmsec 11 2 nil) (lrmpar 4 nil)) (lrmref "LRM" (lrmsec 11 2 nil) (lrmpar 7 nil))))) symb_when) exception_part) nil) (pr_and (lambda (as) (ct_pop *exception_handler_stack* ) (first as)) symb_end))) ;;;;;;;;;;;;;; (def_ada_syntax exception_part ;;;;;;;;;;;;;; (pr_or nil (pr_and (lambda(as) (sc_diana dn_alternative_s as_list (second as))) symb_when (pr_or nil (pr_and (lambda(as) (list (sc_diana dn_alternative as_choice_s (list (sc_diana dn_others)) as_stm_s (third as)))) symb_others oper_goes sequence_of_statements) (pr_and (lambda(as) ;(break look-at-first) (cons (sc_diana dn_alternative as_choice_s (cons (find_name (first as) 'exception) (second as)) as_stm_s (fourth as)) (cond ((fifth as) (diana_get (fifth as) 'as_list)))) ) (pr_and cadr (pr_and (lambda (as) (putback_symbol (first as))) lex_ident) (pr_restrict exception name)) (pr_repeat nil (pr_and (lambda(as) (find_name (cadr as) 'exception)) oper_bar (pr_and cadr (pr_and (lambda (as) (putback_symbol (first as))) lex_ident) (pr_restrict exception name)) )) oper_goes sequence_of_statements (pr_or nil exception_part nil)))) nil)) ;;;-- 5.7 Exit Statements ;;; ;;;-- Syntax 5.7 ;;;-- exit_statement ::= ;;;-- 'exit' [name] ['when' condition]';' ;;;-- ;;; ;;; ;;; STM ::= exit; ;;; NAME_VOID ::= NAME | void; ;;; ;;; exit => as_name_void : NAME_VOID, ;;; as_exp_void : EXP_VOID; ;;; exit => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; exit => sm_stm : LOOP; -- Computed even when there ;;; -- is no name given ;;; -- in the source program. ;;; ;;;;;;;;;;;;;; (def_ada_syntax exit_statement ;;;;;;;;;;;;;; (pr_and (lambda(as) (sc_diana dn_exit as_name_void (cond ((null (second as))(sc_diana dn_void)) (t (find_name (second as) nil))) as_exp_void (cond ((null (third as))(sc_diana dn_void)) (t (third as))))) symb_exit (pr_or nil (pr_restrict named name) nil) (pr_or nil (pr_and (lambda(as) (cond ((not (boolean_expression_p (second as))) (semgripe 'not_bool_exp))) (second as)) symb_when expression) nil) oper_semicolon)) ;;;-- 5.8 Return Statements ;;; ;;;-- Syntax 5.8 ;;;-- return_statement ::= 'return' [expression] ';' ;;;-- ;;; ;;; ;;; STM ::= return; ;;; ;;; return => as_exp_void : EXP_VOID; ;;; return => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;;;;;;;; (def_ada_syntax return_statement ;;;;;;;;;;;;;;;; (pr_and (lambda(as) ;(break return) (let ((rt (first *returntypestack*)) (re (second as))) (cond ((eq rt 'package) (semgripe 'ret_st_in_package)) ((eq rt 'task) (semgripe 'ret_st_in_task)) ((and (null rt) (null re))) ((and (null rt) re) (semgripe 'ret_exp_not_in_fun)) ((and rt (null re)) (rplaca *return_stmt_stack* t) (semgripe 'ret_exp_expected)) ((and re rt) (rplaca *return_stmt_stack* t) (cond ((assignment_compatible re rt)) (t (semgripe 'ret_type_not_compat)))))) (sc_diana dn_return as_exp_void (cond ((null (second as))(sc_diana dn_void)) (t (second as))))) symb_return (pr_or nil expression nil) oper_semicolon)) ;;;-- 5.9 Goto Statements ;;; ;;;-- Syntax 5.9 ;;;-- goto_statement ::= 'goto' name ';' ;;;-- ;;; ;;; ;;; STM ::= goto; ;;; ;;; goto => as_name : NAME; ;;; goto => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;;;;;; (def_ada_syntax goto_statement ;;;;;;;;;;;;;; (pr_and (lambda(as) (%= *goto_count* (1+ *_*)) (let ((goto (sc_diana dn_goto ;;changed as_name to sm_name ++ ct change. sm_name nil)));(find_name (second as) nil)) (ct_push (gotorec goto (second as) **current_block**) *awaiting_label_fixup*) goto)) symb_goto lex_ident;(pr_restrict label name) oper_semicolon))