{########################################################################## #### #### #### Full module name: TYPE_TABLE MODULE OF THE TYPE_CHECKER PROGRAM. #### #### File name: TYPE3TAB.PAS.(3'rd of 3 files reqd for this module.) #### #### Support modules reqd: PASLIB.ERL, SCANNER. #### #### Run time environment: . #### #### Compile time environment: MT MicroSYSTEMS Pascal/MT+v5.25. #### #### Link time environment: MT MicroSYSTEMS Linkmt v5.1. #### #### Copyright (C) 1982 by Haldo Products, Inc. All rights reserved. #### #### 56 Camille Ln, E. Patchogue, NY 11772 #### #### Programmer: Lawrence Adkins. #### #### Module Development/Maintenance History: #### 6-NOV-81 Vers 1.0. File just created. 12-NOV-81 Development of this version completed. 9-JAN-82 Vers 2.0. development begins. 1-MAR-82 Development of this version completed. #### #### ##########################################################################} {#############################################################################} (*-- Assuming that the first_symbol has already been scanned, ---- parse the following Pascal/MT+ productions: ---- ::= | | ---- ---- ::= ( {, } ) ---- ::= .. ---- ::= ---- ::= ---- *) {#############################################################################} PROCEDURE tm9finish_parsing_simple_type (VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec; VAR type_table : ARRAY [ttlobound..tthibound: natural] OF t_type_tab_rec); VAR base, n_of_values, actual_value: integer; BEGIN IF token = toklparen THEN BEGIN cmstore_scalar_type_values (n_of_values, const_table); WITH type_table [last_tt_entry] DO BEGIN lower_bound := 0; upper_bound := n_of_values - 1 END END ELSE IF tm1find_prev_occurance_of_type_id (tokenbuf, last_tt_entry, base, type_table) THEN type_table [last_tt_entry]. base_type_index := base ELSE BEGIN cmfinish_parsing_constant_value (actual_value, const_table); type_table [last_tt_entry]. lower_bound := actual_value; get_next_token; { should be dot_dot token } get_next_token; { should be constant_value or identifier } cmfinish_parsing_constant_value (actual_value, const_table); type_table [last_tt_entry]. upper_bound := actual_value END; get_next_token { should be scolon, END, or rparen tokens } END; { or even rbracket or comma tokens (as with arrays) } {#############################################################################} {--- Find 2 occurances of the same type declaration, compare the two, and ---- remove the latter one. Error if two dont compare. } {#############################################################################} PROCEDURE tmremove_duplicate_type_declaration (VAR type_table : ARRAY [ttlobound..tthibound: natural] OF t_type_tab_rec); VAR j, base, len, last_type_dec_index: integer; rec: t_type_tab_rec; BEGIN IF (record_parsing_status. got_rec_type = 0) AND tm2find_prev_occurance_of_last_type_entry (base, len, type_table) THEN BEGIN {compare all related pairs of records for identity } last_type_dec_index := last_tt_entry - len; FOR j := 0 TO len DO BEGIN rec := type_table [last_type_dec_index + j]; WITH type_table [base + j] DO IF (lower_bound <> rec.lower_bound) OR (upper_bound <> rec.upper_bound) OR (NOT exception (entry_purpose) AND (base_type_index <> rec.base_type_index)) OR (entry_purpose <> rec.entry_purpose) OR ((entry_purpose IN rectype_expansion) AND ((n_of_stacked_fields <> rec.n_of_stacked_fields) OR (NOT exception (field_entry_purpose) AND (field_entry_purpose <> rec.field_entry_purpose)) OR(local_fieldlist_continues<>rec.local_fieldlist_continues) OR (record_nesting <> rec.record_nesting) ) ) THEN BEGIN error (101); { type declared differently from first time } last_tt_entry := last_type_dec_index - 1; exit END; END; { for } last_tt_entry := last_type_dec_index - 1 END { if } END; {#############################################################################} {--- Resolve previously unresolved type declarations. } {--- It is assumed that any references to undefined types occur only ---- in the form TYPE ptr_type_name = ^ defined_or_undefined_type } {#############################################################################} PROCEDURE tmchange_any_refs_to_identical_type_id_with_undef_type (VAR type_table : ARRAY [ttlobound..tthibound: natural] OF t_type_tab_rec); VAR base, len: integer; BEGIN WHILE tm2find_prev_occurance_of_last_type_entry (base, len, type_table) DO IF type_table [base]. entry_purpose = undef_type THEN BEGIN type_table [base-1]. base_type_index := last_tt_entry; WITH type_table [base] DO type_id := concat ('0', type_id) END ELSE exit END; {#############################################################################} {--- Determine the number of entries consumed by the last type declaration, ---- as well as the index to the last previous occurance of the same type ---- identifier. } {#############################################################################} FUNCTION tm2find_prev_occurance_of_last_type_entry (VAR ret_index: integer; VAR entries_consumed: integer; VAR type_table : ARRAY [ttlobound..tthibound: natural] OF t_type_tab_rec): boolean; VAR last_type_dec_index: integer; BEGIN last_type_dec_index := last_tt_entry; WHILE (type_table [last_type_dec_index]. entry_purpose IN rectype_expansion) OR (type_table [last_type_dec_index]. type_id [1] = '0') DO last_type_dec_index := last_type_dec_index - 1; entries_consumed := last_tt_entry - last_type_dec_index; tm2find_prev_occurance_of_last_type_entry := tm1find_prev_occurance_of_type_id (type_table[last_type_dec_index].type_id, (last_type_dec_index - 1), ret_index, type_table) END; {#############################################################################} {--- Looking back from last_index, return the index where the last declar- ---- ation of the specified type identifier may be found. } {#############################################################################} FUNCTION tm1find_prev_occurance_of_type_id (VAR name_string: string132; last_index: integer; VAR ret_index: integer; VAR type_table : ARRAY [ttlobound..tthibound: natural] OF t_type_tab_rec): boolean; VAR i: integer; name_to_find: alfa; BEGIN ret_index := 0; name_to_find := name_string; { reduce length to alfalen characters } tm1find_prev_occurance_of_type_id := false; FOR i :=last_index DOWNTO 1 DO IF (NOT (type_table [i]. entry_purpose IN rectype_expansion)) AND (type_table [i]. type_id = name_to_find) THEN BEGIN tm1find_prev_occurance_of_type_id := true; ret_index := i; exit END END; {#############################################################################} {--- Return true if we dont want to compare the base type entry field } {#############################################################################} FUNCTION exception (entry_purpose: tt_types): boolean; BEGIN exception := entry_purpose IN ttentry_types_where_base_types_wont_compare END; {#############################################################################} {--- Display the current contents of the type table } {#############################################################################} PROCEDURE tmdump_type_table (VAR outfile: text; VAR type_table : ARRAY [ttlobound..tthibound: natural] OF t_type_tab_rec); VAR i: integer; BEGIN writeln (outfile); writeln (outfile, '--- TYPE TABLE DUMP --- '); write (outfile, ' rec# #fld nest recpurpose cont lbound ubound '); writeln (outfile, 'mainpurpose base'); FOR i := 0 TO last_tt_entry DO WITH type_table [i] DO BEGIN write (outfile, i:10); IF NOT (entry_purpose IN rectype_expansion) THEN write (outfile, type_id: 20, ' ':8) ELSE BEGIN write (outfile, n_of_stacked_fields:5, record_nesting:5); write_tt_type_value (outfile, field_entry_purpose); write (outfile, local_fieldlist_continues:5) END; write (outfile, lower_bound:7, upper_bound:7); write_tt_type_value (outfile, entry_purpose); writeln (outfile, base_type_index:5) END; writeln (outfile) END; {#############################################################################} {#############################################################################} PROCEDURE write_tt_type_value (VAR outfile: text; tt_type_value: tt_types); BEGIN CASE tt_type_value OF undef_type : write (outfile, ' undef_type '); predef_type : write (outfile, ' predef_type '); simple_type : write (outfile, ' simple_type '); ptr_type : write (outfile, ' ptr_type '); string_type : write (outfile, ' string_type '); array_type : write (outfile, ' array_type '); file_type : write (outfile, ' file_type '); set_type : write (outfile, ' set_type '); record_type : write (outfile, ' record_type '); recfields : write (outfile, ' recfields '); recfldnestedrecord: write (outfile, ' recfldnested '); recvariant : write (outfile, ' recvariant '); recvarvalues : write (outfile, ' recvarvalues ') END END;