;;; -*- Mode: lisp;package:user; fonts: CPTFONTB -*- ;;; $Header: /ct/interp/adas39a.l,v 1.43 84/12/26 16:40:54 penny Exp $ ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; adas39a.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. ;;;-- 3.9 Declarative Parts ;;; ;;;-- Syntax 3.9 ;;;-- declarative_part ::= ;;;-- {declarative_item} {later_declarative_item} ;;;-- declarative_item ::= declaration | use_clause ;;;-- | representation_specification ;;;-- later_declarative_item ::= body | subprogram_declaration ;;;-- | generic_declaration | use_clause ;;;-- | package_declaration | task_declaration | body_stub ;;;-- body ::= subprogram_body | package_body | task_body ;;;-- ;;; ;;; DECL ::= REP | use; --representation is declarative item ;;; ;;; ITEM_S ::= item_s; ;;; ITEM ::= DECL | package_body | subprogram_body ;;; | task_body; ;;; -- see 3.1, 6.1, 7.1, 10.2 ;;; ;;; item_s => as_list : Seq Of ITEM; ;;; item_s => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;;;;;;;; (def_ada_syntax declarative_item ;;;;;;;;;;;;;;;; (pr_and car ;;; (pr_repeat nil pragma) ; is this really allowed? check-it (pr_or nil pragma ; pragmas are allowed wherever declarations ; are. use_clause obj_num_exc_declaration type_declaration subtype_declaration representation_specification (pr_and (lambda(as) ; subprogram declaration. (ct_pop *returntypestack*) (popcontext) (sc_diana dn_subprogram_decl as_designator (let ((nod (second as))) (diana_put nod (third as) 'sm_spec) nod) as_header (sc_diana dn_procedure as_param_s nil) ; no header info available ; yet. )) symb_procedure (pr_and (lambda(as) (ct_push nil *returntypestack*) (prog1 (add_name (first as) ; procedure name 'procedure (sc_diana dn_proc_id lx_symrep (first as) sm_spec nil sm_body (sc_diana dn_stub)) nil) (pushproccontext))) lex_ident) (pr_or nil (pr_and cadr symb_is generic_instantiation) (pr_and car ;++ (pr_or nil proc_formal_part nil) (pr_or nil (pr_and (lambda(as) ; what do we do with the ; expression ++ (sc_diana dn_rename as_name (second as))) symb_renames (pr_restrict proc_or_entry name) (pr_or nil (pr_and cadr oper_lparen expression oper_rparen) nil)) nil))) oper_semicolon) (pr_and (lambda(as) (ct_pop *returntypestack*) (popcontext) (sc_diana dn_subprogram_decl as_designator (let ((nod (second as))) (diana_put nod (first (third as)) 'sm_spec) (diana_put (first (third as)) (second (third as)) 'as_name_void) nod) as_header (sc_diana dn_function as_param_s nil) )) symb_function (pr_and (lambda(as) (ct_push nil *returntypestack*) (prog1 (add_name `(lex_ident ,(cadr (first as))) ;function name 'function (sc_diana dn_function_id lx_symrep (first as) sm_spec nil sm_body (sc_diana dn_stub) sm_location nil sm_stub nil sm_first nil) nil) (pushproccontext))) (pr_or nil (pr_and (lambda(as) (cond ((not (user_definable_function_p as)) (semgripe 'not_user_definable_operator (implode (cadr (first as)))))) (first as)) lex_string) lex_ident)) (pr_or nil (pr_and cadr symb_is generic_instantiation) (pr_and nil (pr_and (lambda(as) (cond ((first as)(first as)) (t (sc_diana dn_function)))) (pr_or nil funct_formal_part nil)) (pr_and cadr ; temporary fix!++ symb_return (pr_and (lambda (as) (rplaca *returntypestack* (first as)) (first as)) subtype_indication) (pr_or nil (pr_and cadr symb_renames (pr_restrict function name)) nil)))) oper_semicolon) (pr_and (lambda(as) (ct_pop *returntypestack*) (matching_ident (diana_get (second as) 'lx_symrep) (ct_pop *identstack*)) (let ((pkg_id (second as))) (cond ((eq (diana_nodetype_get (third as)) 'dn_instantiation) (let ((instantiation (instantiated_spec (third as)))) (diana_put pkg_id (diana_get instantiation 'sm_spec) 'sm_spec) (diana_put pkg_id (diana_get instantiation 'sm_body) 'sm_body) (let ((**current_block** (diana_get pkg_id 'ct_named_context))) (redeclare_package_declarations (diana_get instantiation 'sm_spec))))) (t (diana_put (second as) ;pkg_id (third as) ;spec 'sm_spec)))) (popcontext) (sc_diana dn_package_decl as_id (second as) as_package_def (third as))) symb_package (pr_and (lambda(as) (ct_push 'package *returntypestack*) (let ((this_pkg (sc_diana dn_package_id lx_symrep (first as)))) (add_name (first as) 'package this_pkg nil) (pushcontext) (diana_put this_pkg **current_block** 'ct_named_context) this_pkg)) lex_ident) (pr_or nil (pr_and (lambda(as) (ct_push nil *identstack*) (sc_diana dn_rename as_name (second as))) symb_renames (pr_restrict package name)) (pr_and cadr symb_is (pr_or nil (pr_and (lambda(as) (ct_push nil *identstack*) (first as)) generic_instantiation) (pr_and (lambda(as) (ct_push (second as) *identstack*) (first as)) package_spec_part (pr_or nil lex_ident nil))))) oper_semicolon) (pr_and (lambda (as) (ct_pop *returntypestack*) (second as)) (pr_and (lambda (as) (ct_push 'task *returntypestack*) (first as)) symb_task) (pr_or nil (pr_and (lambda(as) (popcontext) (matching_ident (first as) (ct_pop *identstack*)) (sc_diana dn_task_decl as_id (first as) as_task_def (second as))) (pr_and (lambda(as) (add_name (first as) 'task (sc_diana dn_var_id lx_symrep (first as) ct_named_context (pushcontext)) nil) ) lex_ident) (pr_or nil (pr_and (lambda(as) (ct_push nil *identstack*) (sc_diana dn_rename as_name (second as))) symb_renames (pr_restrict task name)) (pr_and (lambda(as) (ct_push (third as) *identstack*) (second as)) symb_is task_spec_part (pr_or nil lex_ident nil)) nil)) (pr_and (lambda(as) (matching_ident (second as) (ct_pop *identstack*)) (let* ((ttd (sc_diana dn_var_id lx_symrep (second as) sm_obj_type (third as))) (td (sc_diana dn_task_decl as_id ttd as_task_def (third as)))) (add_name (second as) 'task ttd nil) td)) symb_type lex_ident (pr_or nil (pr_and (lambda(as) (ct_push (third as) *identstack*) (second as)) symb_is task_spec_part (pr_or nil lex_ident nil)) nil))) oper_semicolon) (pr_and (lambda(as) (ct_pop *current_generic_nestitude*) (first as)) generic_specification oper_semicolon)) ) ) ;;;-- Syntax 3.6.B ;;;-- index ::= type_mark 'range' '<>' ;;;-- ;;; ;;; ;;; DSCRT_RANGE ::= index; ;;; ;;; index => as_name : NAME; ;;; index => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;;;;;;;;;; (def_ada_syntax index_range ;;;;;;;;;;; (pr_and (lambda(as) (cond ((and (consp (second as)) (eq (first (second as)) 'oper_dotdot)) ; range (sc_diana dn_range as_exp1 (first as) as_exp2 (second (second as)) sm_base_type (find_type_for_range (first as) (second (second as))))) ((second as) ; constrained. (sc_diana dn_constrained as_name (first as) as_constraint (second as))) (t ;; simple_expression must be a typemark need to check (cond ((eq (diana_nodetype_get (first as)) 'dn_parenthesized) (semgripe 'erroneous_non_range_expression) (first as)) ((and (eq (diana_nodetype_get (first as)) 'dn_used_name_id) (diana_get (first as) 'sm_defn) (memq (diana_nodetype_get (diana_get (first as) 'sm_defn)) '(dn_type_id dn_subtype_id))) (first as)) ((and (eq (diana_nodetype_get (first as)) 'dn_attribute_call) (equal (diana_get (diana_get (diana_get (first as) 'as_name) 'as_id) 'lx_symrep) (ada_ident range))) (first as)) (t (semgripe 'range_in_for_must_be_a_discrete_type) (first as)))) )) simple_expression (pr_or nil (pr_and nil oper_dotdot simple_expression) range_constraint nil))) ;;;-- Syntax 3.7.B ;;;-- component_list ::= ;;;-- component_declaration {component_declaration} ;;;-- | {component_declaration} variant_part | 'null' ';' ;;;-- component_declaration ::= ;;;-- identifier_list ':' subtype_indication ;;;-- [':=' expression] ';' ;;;-- ;;; ;;; ;;; COMP ::= var | null_comp | variant_part; ;;; -- where 'ID' is always a 'comp_id'. ;;; ;;; COMP ::= pragma; -- pragmas are allowed in ;;; -- component declarations ;;; ;;; null_comp => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; DEF_ID ::= comp_id; ;;; ;;; comp_id => lx_srcpos : source_position, ;;; lx_comments : comments, ;;; lx_symrep : symbol_rep; ;;; comp_id => sm_obj_type : TYPE_SPEC, ;;; sm_init_exp : EXP_VOID; ;;; comp_id => cd_position : Integer, ;;; cd_first_bit : Integer, ;;; cd_last_bit : Integer; ;;; ;;;;;;;;;;;;;; (def_ada_syntax component_list ;;;;;;;;;;;;;; (pr_or nil (pr_and (lambda(as) (cons (sc_diana dn_null_comp) nil)) symb_null oper_semicolon) (pr_and (lambda(as) (cond ((null (second as))(first as)) (t (append (first as)(list (second as)))))) (pr_repeat (lambda(as) (mapcar #'(lambda(part) (let ((type (cond ((is_subtype_ind_init (fourth part)) (subtype_ind_init%sub_ind (fourth part))))) (init (cond ((is_subtype_ind_init (fourth part)) (subtype_ind_init%initexp (fourth part))))) (part_type (cond ((is_subtype_ind_init (fourth part)) (subtype_ind_init%sub_ind (fourth part))) (t ; constrained array (first (fourth part)))))) (cond ((and (first as) (null (extract_basetype type))) (semgripe 'incomplete_type))) (cond ((and init (null (assignment_compatible init type))) (semgripe 'init_exp_wrong_type))) (cond ((non_constant_unconstrained_array_type_p type) (cond (init (semgripe 'non_constant_unconstrained_array_type)) (t (semgripe 'unconstrained_array_declaration))))) (sc_diana dn_var as_object_def (let ((def (cond ((is_subtype_ind_init (fourth part)) (and (subtype_ind_init%initexp (fourth part)) (diana_put (subtype_ind_init%initexp (fourth part)) part_type 'sm_exp_type)) (subtype_ind_init%initexp (fourth part))) (t ;array aggregate (if present). (and (second (fourth part)) (diana_put (second (fourth part)) part_type 'sm_exp_type)) (second (fourth part)) )))) (and def (let ((cp (diana_copy def))) (cond ((eq (diana_nodetype_get cp) 'dn_aggregate) (normalize_aggregate cp))) cp))) as_type_spec part_type as_id_s (nreverse (mapcar #'(lambda(id) (add_name (diana_get id 'lx_symrep) 'object (let* ((part_type (cond ((is_subtype_ind_init (fourth part)) (subtype_ind_init%sub_ind (fourth part))) (t ; constrained array. (first (fourth part))))) (compid id)) (diana_put compid (cond ((is_subtype_ind_init (fourth part)) (and (subtype_ind_init%initexp (fourth part)) (diana_put (subtype_ind_init%initexp (fourth part)) part_type 'sm_exp_type)) (subtype_ind_init%initexp (fourth part))) (t ; array aggregate ; (if present) (and (second (fourth part)) (diana_put (second (fourth part)) part_type 'sm_exp_type)) (second (fourth part)))) 'sm_init_exp) (diana_put compid part_type 'sm_obj_type) (diana_put compid compid 'sm_defn) compid) nil)) ;put tparent type defn here.. (cons (first part)(second part))))))) as)) (pr_and nil (pr_and (lambda (as) (let ((node (sc_diana dn_comp_id lx_symrep (first as)))) (adjust_source_pos node -1 -1) node)) lex_ident) (pr_repeat nil (pr_and cadr oper_comma (pr_and (lambda (as) (let ((node (sc_diana dn_comp_id lx_symrep (first as)))) (adjust_source_pos node -1 -1) node)) lex_ident))) oper_colon (pr_or nil subtype_indication_init constrained_array_type_definition_init) oper_semicolon)) (pr_or nil (pr_and (lambda(as) (sc_diana dn_variant_part as_name (first ;++ need to fix this pr. (ada_declared (second as) nil 'object t)) as_variant_s (sc_diana dn_variant_s as_list (fourth as)))) symb_case lex_ident symb_is component_list_when_part symb_end symb_case oper_semicolon) nil)))) (defun static_choicep(ch) (and (diana_nodep ch) (ct_selectq (diana_nodetype_get ch) ((dn_numeric_literal dn_enum_id dn_def_char dn_number_id) t) ((dn_type_id ;check that it is statically constrained dn_derived dn_constrained) (static_choicep (find_constraint_for ch))) (dn_subtype_id (static_choicep (diana_get ch 'sm_type_spec))) (dn_range (and (static_choicep (diana_get ch 'as_exp1)) (static_choicep (diana_get ch 'as_exp2)))) (dn_used_name_id (static_choicep (diana_get ch 'sm_defn))) ((dn_var_id dn_const_id) nil) (otherwise (cond ((neq (fe_static_eval ch) '*diana_node_not_static_expression*) t)))))) ;;;;;;;;;;;;;;;;;;;;;;;; (def_ada_syntax component_list_when_part ;;;;;;;;;;;;;;;;;;;;;;;; (pr_and cadr symb_when (pr_or nil (pr_and (lambda(as) (list (sc_diana dn_variant as_choice_s (list (sc_diana dn_others)) as_record (sc_diana dn_inner_record as_list (third as))))) symb_others oper_goes component_list) (pr_and (lambda(as) (let ((chs (cons (first as)(second as)))) (mapc #'(lambda (ch) (cond ((null (static_choicep ch)) (semgripe 'not_static_choice (source_region%linenumber (diana_get ch 'lx_srcpos)))))) chs) (cons (sc_diana dn_variant as_choice_s chs as_record (sc_diana dn_inner_record as_list (fourth as))) (fifth as)))) choice_range (pr_repeat nil (pr_and cadr oper_bar choice_range)) oper_goes component_list (pr_or nil component_list_when_part nil))))) ;;;;;;;;;;;; (def_ada_syntax choice_range ;;;;;;;;;;;; (pr_and (lambda(as) (cond ((and (consp (second as)) (eq (first (second as)) 'oper_dotdot)) ; range (sc_diana dn_range as_exp1 (first as) as_exp2 (second (second as)) sm_base_type (find_type_for_range (first as) (second (second as))))) ((null (second as)) ; expression. (first as)) (t ; constrained. (sc_diana dn_constrained as_name (first as) as_constraint (second as))))) simple_expression (pr_or nil range_constraint (pr_and nil oper_dotdot simple_expression) nil))) ;;;-- 3.7.1 Discriminants ;;; ;;;-- Syntax 3.7.1 ;;;-- discriminant_part ::= ;;;-- '(' discriminant_declaration ;;;-- {';' discriminant_declaration}')' ;;;-- discriminant_declaration ::= ;;;-- identifier_list ':' subtype_indication [:= expression] ;;;-- ;;; ;;; ;;; VAR_S ::= var_s; ;;; ;;; var_s => as_list : Seq Of VAR; ;;; var_s => lx_srcpos : source_position, ;;; lx_comments : comments; ;;; ;;; VAR ::= var; -- where 'ID' is always a 'dscrmt_id' ;;; ;;; VAR ::= pragma; -- pragma can occur after ';' ;;; -- in discriminant list ;;; ;;; DEF_ID ::= dscrmt_id; ;;; -- see section 3.2.A ;;; ;;; dscrmt_id => lx_srcpos : source_position, ;;; lx_comments : comments, ;;; lx_symrep : symbol_rep; ;;; dscrmt_id => sm_obj_type : TYPE_SPEC, ;;; sm_init_exp : EXP_VOID; ;;; dscrmt_id => cd_position : Integer, ;;; cd_first_bit : Integer, ;;; cd_last_bit : Integer; ;;; ;;;;;;;;;;;;;;;;; (def_ada_syntax discriminant_part ;;;;;;;;;;;;;;;;; (pr_and cadr (pr_and (lambda (as) (setq *numdiscs* 0 *numinitexp* 0) (first as)) oper_lparen) discriminant_part_body (pr_and (lambda (as) (cond ((and (> *numinitexp* 0) (> *numdiscs* *numinitexp*)) (semgripe 'all_or_none_of_discs_default))) (first as)) oper_rparen))) ;;;;;;;;;;;;;;;;;;;;;; (def_ada_syntax discriminant_part_body ;;;;;;;;;;;;;;;;;;;;;; (pr_and (lambda(as) (let* ((vars (sc_diana dn_dscrmt_var_s as_list (cons (sc_diana dn_var as_id_s (mapcar '(lambda(id) (%= *numdiscs* (1+ *_*)) (cond ((subtype_ind_init%initexp (fourth as)) (%= *numinitexp* (1+ *_*)))) (add_name id 'object (let ((did (sc_diana dn_dscrmt_id lx_symrep id sm_obj_type (subtype_ind_init%sub_ind (fourth as)) sm_init_exp (subtype_ind_init%initexp (fourth as)) ))) (diana_put did did 'sm_defn) ;check each disc is a dscrt type (cond ((and (subtype_ind_init%sub_ind (fourth as)) (not (is_discrete_subtype (subtype_ind_init%sub_ind (fourth as)) nil))) (semgripe 'disc_not_dscrt))) did) nil)) (cons (first as)(second as))) as_type_spec (subtype_ind_init%sub_ind (fourth as)) as_object_def (subtype_ind_init%initexp (fourth as)) ) (and (fifth as)(diana_get (fifth as) 'as_list)))))) vars)) lex_ident (pr_repeat nil (pr_and cadr oper_comma lex_ident)) oper_colon subtype_indication_init (pr_or nil (pr_and cadr oper_semicolon discriminant_part_body) nil)))