This is 4c.c in view mode; [Download] [Up]
/* * Copyright (C) 1985-1992 New York University * * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for * warranty (none) and distribution info and also the GNU General Public * License for more details. */ #include "4.h" #include "attr.h" #include "setprots.h" #include "libprots.h" #include "miscprots.h" #include "smiscprots.h" #include "errmsgprots.h" #include "nodesprots.h" #include "dclmapprots.h" #include "evalprots.h" #include "chapprots.h" static int prev_error_message; static Triplet *is_partition(Tuple, int, int); static Tuple sort_case(Tuple); static int tcompar(Triplet **, Triplet **); static int abs_val(int); static void complete_a_aggregate(Tuple, Tuple, Symbol, int, Node); static void complete_component(Tuple, Tuple, Symbol, int, Node); static Node new_comp_assoc(Symbol, Node); static void resolve_r_component(Node, Symbol, Tuple); static Symbol check_discriminant_dependence(Symbol, Tuple); static int in_gen_types(Symbol); static int in_multiple_types(Symbol); static int is_integer_type(Symbol); static Triplet *triplet_new(); int can_constrain(Symbol d_type) /*;can_constrain*/ { /* Determine whether an object, actual parameter, type def, etc. can * receive a constraint.The predicate -is_unconstrained- used in decla- * rations is too weak here, because it returns false on discriminated * records with default values. */ if ((NATURE(d_type) == na_array) || (is_record(d_type) && NATURE(d_type) != na_subtype && has_discriminants(d_type))) return TRUE; else return FALSE; } Set valid_array_expn(Node expn) /*;valid_array_expn*/ { /* Called to validate indexing and slicing operations. The array name may * be overloaded, and may also be an access to an array type. */ Node a_expn, i_node; Set array_types, types, rset; Tuple index_list; Node index; Symbol n, a_t, t; int i, exists, forall; Symbol i_t; Forset fs1, fs2; Fortup ft1; if (cdebug2 > 3) TO_ERRFILE("AT PROC : valid_array_expn"); a_expn = N_AST1(expn); i_node = N_AST2(expn); resolve1(a_expn); types = N_PTYPES(a_expn); index_list = N_LIST(i_node); array_types = set_new(0); /* To collect valid types*/ FORTUP(index = (Node), index_list, ft1); n = N_UNQ(index); if (N_KIND(index) == as_simple_name && n != (Symbol)0 && is_type(n)) /* In the case of a slice, */ N_PTYPES(index) = set_new1((char *)TYPE_OF(n)); /* may be a type mark.*/ else resolve1(index); ENDFORTUP(ft1); #ifdef TBSN if (cdebug2 > 3) TO_ERRFILE('index_list ' + str index_list); #endif /* Now select those array types that are compatible with given indices.*/ FORSET(a_t = (Symbol), types, fs1); t = a_t; if (is_access(t)) { if (is_fully_private(t)) { /* Cannot dereference an access to fully private type.*/ if (set_size(array_types) == 1) { premature_access(t, a_expn); return set_new(0); } else continue; } else t = (Symbol) designated_type(t); } #ifdef TBSN if (cdebug2 > 3) { TO_ERRFILE('type ' + str t); TO_ERRFILE('# dims t ' + str no_dimensions(t)); } #endif /* Discard incompatible array types */ if (!is_array(t) || no_dimensions(t) != tup_size(index_list)) continue; /* Now verify all indices in turn.*/ forall = TRUE; FORTUPI(index = (Node), index_list, i, ft1); exists = FALSE; FORSET(i_t = (Symbol), N_PTYPES(index), fs2); if (compatible_types(i_t, (Symbol) index_types(t)[i])) { exists = TRUE; break; } ENDFORSET(fs2); if (exists == FALSE) { forall = FALSE; break; } ENDFORTUP(ft1); if (forall) /* a valid array type*/ array_types = set_with(array_types, (char *)a_t); ENDFORSET(fs1); #ifdef TBSN if (cdebug2 > 3) TO_ERRFILE('valid_array_expn ' + str array_types); #endif N_PTYPES(a_expn) = array_types; rset = set_new(0); FORSET(a_t = (Symbol), array_types, fs1); if (is_access(a_t)) rset = set_with(rset, (char *) designated_type(a_t)); else rset = set_with(rset, (char *) a_t); ENDFORSET(fs1); return rset; } Symbol complete_array_expn(Node expn, Symbol c_type) /*;complete_array_expn*/ { /* Called to complete the validation of an index or slice expression. The * context type is the element type for indexing, and the array type for * slicing . The array expression may yield an access type, in which case * a dereference operation is emitted now. */ Node a_expn, index_list, a_node; Set array_types; Symbol array_type, a_t, t, c, access_type; Forset fs1; if (cdebug2 > 3) TO_ERRFILE("AT PROC : complete_array_expn"); a_expn = N_AST1(expn); index_list = N_AST2(expn); array_types = N_PTYPES(a_expn); array_type = (Symbol)0; /* Iterate over array types to find unique one satisfying context.*/ FORSET(a_t = (Symbol), array_types, fs1); t = (is_access(a_t)) ? (Symbol)designated_type(a_t): a_t; c = (N_KIND(expn) == as_slice) ? t: (Symbol) (component_type(t)); if (compatible_types(c_type, c)) { if (array_type == (Symbol)0) { /* One match found.*/ array_type = t; access_type = a_t; /* Maybe an access.*/ } else { /* If it is ambiguous, then it must an overloaded function*/ /* that returns (an access to) an array.*/ array_type = symbol_any; } } ENDFORSET(fs1); if (array_type == symbol_any) { remove_conversions(a_expn); /* last chance. */ if (set_size(N_PTYPES(a_expn)) == 1) { array_type = (Symbol) set_arb(N_PTYPES(expn)); access_type = array_type; if (is_access(array_type)) array_type = (Symbol) designated_type(access_type); } else { /* still ambiguous */ /* SETL sends {'indexing'}, in C, send {'any'} */ type_error(set_new1((char *) symbol_any), c_type, set_size(N_PTYPES(a_expn)), expn); } } if (array_type == (Symbol)0) { /* SETL sends {'indexing'}, in C, send {'any'} */ type_error(set_new1((char *) symbol_any), c_type, set_size(N_PTYPES(a_expn)), expn); array_type = symbol_any; } if (array_type != access_type) { /* Insert dereference. */ a_node = copy_node(a_expn); N_KIND(a_expn) = as_all; N_AST1(a_expn) = a_node; N_AST2(a_expn) = N_AST3(a_expn) = N_AST4(a_expn) = (Node) 0; N_PTYPES(a_expn) = set_new1((char *) array_type); } resolve2(a_expn, array_type); /* and resolve. */ return array_type; } void valid_selected_expn(Node expn) /*;valid_selected_expn*/ { /* Use the name of the selector to determine the possible types of obj, * which may be a function returning (an access to) a record or task type * The possible types of the expression are those of the selected comps. */ Node obj, s_node; Set types1, valid_t; Symbol o_t, t, comp; char *selector; Forset fs1; Declaredmap decls; obj = N_AST1(expn); s_node = N_AST2(expn); selector = N_VAL(s_node); resolve1(obj); types1 = N_PTYPES(obj); valid_t = set_new(0); FORSET( o_t = (Symbol), types1, fs1); t = o_t; if (is_access(o_t))t = (Symbol) designated_type(o_t); if (is_record(t)) decls = (Declaredmap) (declared_components(base_type(t))); else if (is_task_type(t)) decls = DECLARED(t); else continue; comp = dcl_get(decls, selector); if (comp != (Symbol)0) { if (is_access(o_t) && is_fully_private(o_t) && NATURE(comp) != na_discriminant) { /*$ Can't dereference.*/ if (set_size(types1) == 1) { premature_access(o_t, obj); return; } else continue; } else valid_t = set_with(valid_t, (char *) TYPE_OF(comp)); } ENDFORSET(fs1); if (set_size(valid_t) == 0) pass1_error("invalid selector name", "4.1.3", s_node); N_PTYPES(expn) = valid_t; } Symbol complete_selected_expn(Node expn, Symbol c_type) /*;complete_selected_expn*/ { /* Complete the resolution of a selected component expression, by * choosing the one that yields the context_type. If the type of the * object selected from is an access type, emit a dereference. */ Node obj, s_node, acc_obj; Set types1; Symbol comp_t, o_t, t, comp, obj_t, c; int out_c; Forset fs1; char *selector; Declaredmap decls; obj = N_AST1(expn); s_node = N_AST2(expn); selector = N_VAL(s_node); types1 = N_PTYPES(obj); comp_t = (Symbol)0; FORSET( o_t = (Symbol), types1, fs1); t = (is_access(o_t)) ? (Symbol) designated_type(o_t): o_t; if (is_record(t)) decls = (Declaredmap) declared_components(base_type(t)); else if (is_task_type(t)) decls = DECLARED(t); c = dcl_get(decls, selector); if (c != (Symbol)0 && compatible_types(TYPE_OF(c), c_type)) { comp = c; if (comp_t == (Symbol)0) { comp_t = TYPE_OF(comp); /* Found a match*/ N_UNQ(s_node) = comp; obj_t = o_t; } else /* ambiguous call to some*/ obj_t = symbol_any; } ENDFORSET(fs1); if (obj_t == symbol_any) { remove_conversions(obj); /* last hope. */ if (set_size(N_PTYPES(obj)) != 1) { #ifdef TBSL type_error(set_new1(symbol_selection), (Symbol)0, set_size(N_PTYPES(obj)), expn); #endif return (Symbol)0; } else obj_t = (Symbol) set_arb(N_PTYPES(obj)); } out_c = out_context; /* This is a valid context for the use of an out parameter, if * it is an assigment to a component of it, or if it is a reading * of a discriminant. */ out_context = (out_c || NATURE(comp) == na_discriminant) ? TRUE:FALSE; if (is_access(obj_t)) { obj_t = (Symbol) designated_type(obj_t); /* Introduce explicit dereference. */ acc_obj = copy_node(obj); N_KIND(obj) = as_all; N_AST2(obj) = N_AST3(obj) = N_AST4(obj) = (Node) 0; N_AST1(obj) = acc_obj; N_PTYPES(obj) = set_new1((char *)obj_t); } resolve2(obj, obj_t); out_context = out_c; return comp_t; } static Triplet *is_partition(Tuple choice_tuple, int choice_tuple_size, int exist_other_choice) /*;is_partition*/ { /* Checks if the ranges of the choice_nodes in a named array aggregate form * a partition. * For example: (1|2|4 =>2, 5..10 =>3, 3 =>2, NUM => 4) where you can find * simple_choices, a range_choice and a choice_unresolved. This will be a * partition if the type_mark NUM is disjoint with {1..10} assuming that * the bounds of the array are (1..NUM'LAST). A range such as 7..4 is a * null range. It is permitted only if alone in the array aggregate. * This function returns a pointer to a Triplet. This Triplet gives the * final range of the aggregate. Complete_a_aggregate checks after whether * the range of the aggregate is the same than the range of the array. It * uses the system call 'qsort' to sort the ranges by their lower bound * and then uses this sorted list to verify that it is a partition. */ int lbd, ubd = 0, ubd_save; Triplet *i_trip; Node choice; int i; if (choice_tuple_size != 0) { /* 1. sort the set of choices giving a tuple */ choice_tuple = sort_case(choice_tuple); /* 2. pass over choice_tuple checking that: * - there are only legal null ranges * - there are no overlapping ranges * - if the array aggregate does not have an others * then there are no missing associations */ for (i = 1; (i <= choice_tuple_size); i++) { ubd_save = ubd; lbd = ((Triplet *) choice_tuple[i])->inf; ubd = ((Triplet *) choice_tuple[i])->sup; choice = ((Triplet *) choice_tuple[i])->choice_node; /* 1. Check for a null range. */ if ((lbd > ubd) && (choice_tuple_size > 1 || exist_other_choice)) { #ifdef ERRNUM errmsgn(284, 285, choice); #else errmsg( "A null range in array aggregate must be the only choice", "4.3.2.(3)", choice); #endif prev_error_message = 1; return (Triplet *)0; } /* 2. Check that the ranges do not overlap */ else if ((lbd <= ubd_save) && (i > 1)) { #ifdef ERRNUM errmsgn(286, 287, choice); #else errmsg( "Component is not allowed to be specified more than once", "4.3.(6)", choice); #endif prev_error_message = 1; return (Triplet *)0; } /* 3. Check that the intersection between the ranges is not null*/ else if ((i > 1) && (!exist_other_choice) && (lbd != ubd_save+1)) { #ifdef ERRNUM errmsgn(288, 287, choice); #else errmsg("Missing association in array aggregate", "4.3.(6)", choice); #endif prev_error_message = 1; return (Triplet *)0; } } i_trip = triplet_new(); i_trip->inf = ((Triplet *) choice_tuple[1])->inf; i_trip->sup = ((Triplet *) choice_tuple[choice_tuple_size])->sup; return (i_trip); } } static Tuple sort_case(Tuple tuple_to_sort) /*;sort_case*/ { /* This function sorts a tuple of triples based on the value of the * first element */ qsort((char *) &tuple_to_sort[1], tup_size(tuple_to_sort), sizeof (char *), (int (*)(const void *, const void *))tcompar); return tuple_to_sort; } static int tcompar(Triplet **ptup1, Triplet **ptup2) /*;tcompar*/ { Triplet *tup1, *tup2; int n1, n2; tup1 = *ptup1; tup2 = *ptup2; n1 = (int) (tup1->inf); n2 = (int) (tup2->inf); if (n1 == n2) return 0; else if (n1 < n2) return -1; else return 1; } static int abs_val(int x) /*;abs_val*/ { return (x >= 0) ? x : -x; } void complete_aggregate(Symbol agg_type, Node expn) /*;complete_aggregate*/ { /* Given the context type, resolve the aggregate components. For an array * type we pass index and component types separately to the recursive * routine complete_a_aggregate. For record types only the base type is * needed here. Any required constraints are imposed in resolve2. */ if (cdebug2 > 3) TO_ERRFILE("AT PROC : complete_aggregate"); if (is_limited_type(agg_type)) { #ifdef ERRNUM id_errmsgn(289, agg_type, 34, expn); #else errmsg_id("aggregates not available for limited type %", agg_type, "7.4.4", expn); #endif } if (is_array(agg_type)) { /* if the context allows sliding, the bounds of the aggregate need * only be verified against the unconstrained type. */ if (full_others) complete_a_aggregate(index_types(agg_type), index_types(agg_type), component_type(agg_type), can_constrain(agg_type), expn); else complete_a_aggregate(index_types(agg_type), index_types(TYPE_OF(agg_type)), component_type(agg_type), can_constrain(agg_type), expn); } else if (is_record(agg_type)) complete_r_aggregate(base_type(agg_type), expn); else { #ifdef ERRNUM errmsgn(290, 10, expn); #else errmsg("Invalid context for aggregate", "none", expn); #endif } } static void complete_a_aggregate(Tuple indices, Tuple base_indices, Symbol comp_type, int is_unc, Node expn) /*;complete_a_aggregate*/ { /* Complete processing of an array aggregate. The tree is normalized as * follows: * N_KIND = as_array_aggregate * N_AST = [list_node, others_node] * where list_node has two entries: * N_AST = [pos_list, nam_list] * The first two are list nodes. The elements of N_LIST(nam_list) are * pairs [choice_list, expression]. The N_KIND of choice nodes are * as_simple_choice and as_range_choice. A simple_choice includes a * type name specifiying a range. */ Tuple arg_list, pos_list, nam_list, tup, b_itup, itup; Node others_node, last_arg, choice_list, c_expr, lexpn; Node arg, i_expr, range_constraint, choice, pos_node, nam_node; Symbol type_mark, indxt, b_indxt; Fortup ft1, ft2; int i, n, nn; int c_ind, exist_other_choice, lbd, ubd, lbd_val, ubd_val; int static_test, choice_tuple_size; int raises; Tuple choice_tuple; Triplet *aggr_range; Node lw_bd, hg_bd, lo_bd, up_bd, simple_expr1, simple_expr2; char *nchoice; if (cdebug2 > 3) TO_ERRFILE("AT PROC : complete_a_aggregate"); arg_list = N_LIST(expn); b_indxt = (Symbol) base_indices[1]; indxt = (Symbol) indices[1]; others_node = OPT_NODE; pos_list = tup_new(0); nam_list = tup_new(0); choice_tuple_size = 0; static_test = 1; c_ind = 1; exist_other_choice = 0; prev_error_message = 0; raises = FALSE; /* STEP 1. * Remove the OTHERS choice from the arggregate list if it is the last * component and place in -others_choice-. Otherwise if it appears * elsewhere in the aggregate it will be noted as a error later. */ last_arg = (Node) arg_list[tup_size(arg_list)]; if (N_KIND(last_arg) == as_choice_list) { choice_list = N_AST1(last_arg); c_expr = N_AST2(last_arg); tup = N_LIST(choice_list); choice = (Node) tup[1]; if (N_KIND(choice) == as_others_choice) { exist_other_choice = 1; others_node = c_expr; if (is_unc || (!is_static_subtype(indxt) && tup_size(arg_list)>1)) { #ifdef ERRNUM errmsgn(291, 292, last_arg); #else errmsg("OTHERS choice not allowed in this context", "4.3.2", last_arg); #endif } /* process anyway*/ tup_frome(arg_list); resolve1(c_expr); n = tup_size(base_indices); nn = tup_size(indices); if (nn > 0 && n > 0) { b_itup = tup_new(n-1); itup = tup_new(n-1); for (i = 1; i < n; i++) b_itup[i] = base_indices[i+1]; for (i = 1; i < nn; i++) itup[i] = indices[i+1]; complete_component(itup, b_itup, comp_type, is_unc, c_expr); raises = raises || (N_KIND(c_expr) == as_raise); } } } /* STEP 2. * After any others clause has been processed, process the named and * positional associations */ FORTUP(arg = (Node), arg_list, ft1); if (N_KIND(arg) == as_choice_list) { /* STEP 2a. * Process named association choice list */ choice_list = N_AST1(arg); c_expr = N_AST2(arg); resolve1(c_expr); n = tup_size(base_indices); nn = tup_size(indices); if (nn > 0 && n > 0) { b_itup = tup_new(n-1); itup = tup_new(n-1); for (i = 1; i < n; i++) b_itup[i] = base_indices[i+1]; for (i = 1; i < nn; i++) itup[i] = indices[i+1]; complete_component(itup, b_itup, comp_type, is_unc, c_expr); raises = raises || (N_KIND(c_expr) == as_raise); } else chaos("complete_a_aggregate - indices null"); /* STEP 2b. * Process each choice in the choice list */ FORTUP(choice = (Node), N_LIST(choice_list), ft2); n = -1; if (N_KIND(choice) == as_choice_unresolved) { /* Case: choice_unresolved: * If the index expression is an identifier, it must be * a type name or an object. */ i_expr = N_AST1(choice); find_old(i_expr); type_mark = N_UNQ(i_expr); if (is_type(type_mark)) { /* Subcase: type type_mark of choice_unresolved * check that it is either the only choice -or- is * static... * set the N_KIND to a as_simple_name * check that the type_mark is compatible with * the base index type */ tup = SIGNATURE(type_mark); lo_bd = (Node) tup[2]; up_bd = (Node) tup[3]; if ((!is_static_expr(lo_bd))||(!is_static_expr(up_bd))){ if ((tup_size(arg_list)>1) || exist_other_choice) { errmsg( "Non static choice in array aggregate must be the only choice", "4.3.2.(3)", choice); } static_test = 0; } else { lbd_val = INTV((Const) N_VAL(lo_bd)); ubd_val = INTV((Const) N_VAL(up_bd)); } N_KIND(choice) = as_simple_name; nchoice = N_VAL(choice); /* preserve N_VAL */ N_AST1(choice) = (Node)0; N_AST2(choice) = (Node)0; N_AST3(choice) = (Node)0; N_AST4(choice) = (Node)0; N_UNQ(choice) = type_mark; N_VAL(choice) = nchoice; /* preserve N_VAL */ if (!compatible_types(type_mark, b_indxt)) { #ifdef ERRNUM errmsgn(293, 294, choice); #else errmsg("invalid type mark in array aggregate", "4.3", choice); #endif return; } } else { /* single association*/ /* Subcase: simple_choice of choice_unresolved * this is a single association * set the N_KIND to a as_simple_name check that * it is either the only choice -or- is static... */ N_KIND(choice) = as_simple_choice; i_expr = N_AST1(choice); check_type(base_type(b_indxt), i_expr); if (N_TYPE(i_expr) == symbol_any) static_test = 0; else if (!is_static_expr(i_expr)) { if ((tup_size(arg_list)>1) || exist_other_choice) { #ifdef ERRNUM errmsgn(295, 285, choice); #else errmsg( "Non static choice in array aggregate must be the only choice", "4.3.2.(3)", choice); #endif } static_test = 0; } else { lbd_val = INTV((Const) N_VAL(i_expr)); ubd_val = INTV((Const) N_VAL(i_expr)); } } } /* Case: as_simple_choice * The association is known to be a simple expression. * check that the type of the expression * check that it is either the only choice -or- is static... */ else if (N_KIND(choice) == as_simple_choice) { i_expr = N_AST1(choice); adasem(i_expr); check_type(base_type(b_indxt), i_expr); if (N_TYPE(i_expr) == symbol_any) static_test = 0; else if (!is_static_expr(i_expr)) { if ((tup_size(arg_list) > 1) || exist_other_choice) { #ifdef ERRNUM errmsgn(295, 285, choice); #else errmsg( "Non static choice in array aggregate must be the only choice", "4.3.2.(3)", choice); #endif } static_test = 0; } else { lbd_val = INTV((Const) N_VAL(i_expr)); ubd_val = INTV((Const) N_VAL(i_expr)); } } /* Case: range_choice */ else if (N_KIND(choice) == as_range_choice) { i_expr = N_AST1(choice); check_type(b_indxt, i_expr); if (N_KIND(i_expr) == as_subtype) { /* Subcase: expression is subtype in range_choice * Extract the constraint itself is static, reformat * choice as range else check that it is the only * choice */ range_constraint = N_AST2(i_expr); copy_attributes(range_constraint, choice); simple_expr1 = N_AST1(range_constraint); simple_expr2 = N_AST2(range_constraint); if (N_TYPE(i_expr) == symbol_any) static_test = 0; else if ((!is_static_expr(simple_expr1)) || (!is_static_expr(simple_expr2))) { if ((tup_size(arg_list) > 1) || exist_other_choice){ #ifdef ERRNUM errmsgn(295, 285, choice); #else errmsg( "Non static choice in array aggregate must be the only choice", "4.3.2.(3)", choice); #endif } static_test = 0; } else { lbd_val = INTV((Const) N_VAL(simple_expr1)); ubd_val = INTV((Const) N_VAL(simple_expr2)); } } else { /*attribute RANGE.*/ /* Subcase: attribute range subtype in range_choice * this means that it is an attrtibute range */ static_test = 0; } } /* Case: others choice (illegal at this point) */ else if (N_KIND(choice) == as_others_choice) { #ifdef ERRNUM errmsgn(296, 294, choice); #else errmsg("OTHERS must be the last aggregate component", "4.3", choice); #endif return; } /* STEP 2c. * After processing the choice if it is static then add to * choice list to be tested with is_partition */ if (static_test) { aggr_range = triplet_new(); aggr_range->inf = lbd_val; /*bounds and node of the curr */ aggr_range->sup = ubd_val; /*choice_node for is_partition*/ aggr_range->choice_node = choice; if (c_ind == 1) choice_tuple = tup_new1((char *) aggr_range); else choice_tuple =tup_with(choice_tuple,(char *)aggr_range); } c_ind++; ENDFORTUP(ft2); /* choice within a named choice list */ /* STEP 2d. * Add the choice list to the tuple of named associations */ nam_list = tup_with(nam_list, (char *) arg); } /* STEP 3. * Process positional components... */ else { /* Positional component. */ resolve1(arg); n = tup_size(base_indices); nn = tup_size(indices); if (nn > 0 && n > 0) { b_itup = tup_new(n-1); itup = tup_new(n-1); for (i = 1; i < n; i++) b_itup[i] = base_indices[i+1]; for (i = 1; i < nn; i++) itup[i] = indices[i+1]; complete_component(itup, b_itup, comp_type, is_unc, arg); raises = raises || (N_KIND(arg) == as_raise); } else chaos("complete_a_aggregate - indices null"); pos_list = tup_with(pos_list, (char *) arg); } ENDFORTUP(ft1); /* end of processing the choice lists */ /* STEP 4. * Perform the final checks. * A. Check that either the name list or the position list is null * B. Check for valid context for Others choice */ if (tup_size(pos_list) > 0 && tup_size(nam_list) > 0) { #ifdef ERRNUM l_errmsgn(297, 298, 292, expn); #else errmsg_l("In a positional aggregate only named association ", "allowed is OTHERS", "4.3.2", expn); #endif return; } else if (others_node != OPT_NODE && !full_others && tup_size(nam_list) !=0){ #ifdef ERRNUM errmsgn(299, 300, others_node); #else errmsg("Invalid context for OTHERS and named associations", "4.3.2(6)", others_node); #endif return; } tup = SIGNATURE(indxt); /*range of the array.*/ lw_bd = (Node) tup[2]; hg_bd = (Node) tup[3]; /* STEP 5. * Perform check is it is static and named * If it is a partition then check: * A. If the range is out of bounds (base index) considering sliding * B. if the size of the choice range is less than the index range * C. if the size of the choice range is greater that the index range * D. if the choice range is null and the index range is not */ if (n == -1 && static_test) { choice_tuple_size = tup_size(choice_tuple); aggr_range = is_partition(choice_tuple, choice_tuple_size, exist_other_choice); if (!prev_error_message && !exist_other_choice) { lbd = aggr_range->inf; ubd = aggr_range->sup; tup = SIGNATURE(b_indxt); /*range of the indices.*/ lo_bd = (Node) tup[2]; up_bd = (Node) tup[3]; if ((is_static_expr(lo_bd)) && (is_static_expr(up_bd))) { lbd_val = INTV((Const) N_VAL(lo_bd)); ubd_val = INTV((Const) N_VAL(up_bd)); /* Check A */ if ((lbd_val > lbd || ubd_val < ubd) && (ubd_val > lbd_val && ubd > lbd) /*Non-null range*/ && full_others) { /* Does not check anything if the subtype_range or the * aggregate_range is null, according to test c43206a. */ raises = TRUE; } } if (!is_unc) { if ((is_static_expr(lw_bd)) && (is_static_expr(hg_bd))) { lbd_val = INTV((Const) N_VAL(lw_bd)); ubd_val = INTV((Const) N_VAL(hg_bd)); /* TBSL : ubd_val-lbd_val may be superior to INTEGER'LAST. * Use multiprecision. */ /* Check B */ if ((ubd_val > lbd_val && ubd > lbd) /*Non-null range*/ && (abs_val(ubd_val - lbd_val) < abs_val(ubd - lbd))) raises = TRUE; /* TBSL : ubd_val-lbd_val may be superior to INTEGER'LAST. * Use multiprecision. */ /* Check C */ else if ((ubd_val > lbd_val && ubd > lbd) /*Non-null range*/ && (abs_val(ubd_val - lbd_val) > abs_val(ubd - lbd))) { /* CONSTRAINT_ERROR may be raised according to test * c48009f instead of: * #ifdef ERRNUM * errmsgn(288, 287, expn); * #else * errmsg("Missing association in array aggregate", * "4.3.(6)", expn); * #endif */ raises = TRUE; } /* Check D */ else if (ubd_val < lbd_val && ubd > lbd) { raises = TRUE; } } } } } /* STEP 6. * Perform check is it is position, not others and unconstrained */ if (n != -1 && !is_unc && !exist_other_choice) { /*Positional components*/ if ((is_static_expr(lw_bd)) && (is_static_expr(hg_bd))) { lbd_val = INTV((Const) N_VAL(lw_bd)); ubd_val = INTV((Const) N_VAL(hg_bd)); /* TBSL : ubd_val-lbd_val may be superior to INTEGER'LAST. * Use multiprecision. */ if (tup_size(pos_list) != abs_val(ubd_val-lbd_val) + 1) { raises = TRUE; } } } /* STEP 7. * Proccess an others choice by itself by converted into a named * association */ if (tup_size(pos_list) == 0 && tup_size(nam_list) == 0) { if ((N_KIND(lw_bd) == as_ivalue || N_KIND(lw_bd) == as_discr_ref) && (N_KIND(hg_bd) == as_ivalue || N_KIND(hg_bd) == as_discr_ref)) { choice = node_new(as_range); N_AST1(choice) = copy_tree(lw_bd); N_AST2(choice) = copy_tree(hg_bd); arg = node_new(as_choice_list); N_AST1(arg) = node_new(as_list); N_LIST(N_AST1(arg)) = tup_new1( (char *)choice); N_AST2(arg) = others_node; nam_list = tup_new1( (char *)arg); others_node = OPT_NODE; } } /* If any component or subaggregate raises constraint error, replace the * whole aggregate by a raise node. */ if (raises) { create_raise(expn, symbol_constraint_error); return; } /* STEP 8. * Create the pos and name lists nodes */ pos_node = node_new(as_list); nam_node = node_new(as_list); N_LIST(pos_node) = pos_list; N_LIST(nam_node) = nam_list; N_KIND(expn) = as_array_aggregate; N_UNQ(expn) = sym_new(na_void); N_LIST(expn) = tup_new(0); /* no further need for it.*/ lexpn = node_new(as_aggregate_list); N_AST1(lexpn) = pos_node; N_AST2(lexpn) = nam_node; N_AST1(expn) = lexpn; N_AST2(expn) = others_node; N_AST4(expn) = (Node) 0; } static void complete_component(Tuple indices, Tuple b_indices, Symbol comp_type, int is_unc, Node expn) /*;complete_component*/ { /* Complete the resolution of a component of an array aggregate. If it * is a multidimensional aggregate, the component itself is an array and * a recursive call is made with the remaining indices. String literals * are handled in their own routine. */ Node expn2; if (cdebug2 > 3) TO_ERRFILE("AT PROC complete_component"); if (tup_size(b_indices) == 0) res2_check(expn, comp_type); else if (N_KIND(expn) == as_aggregate) complete_a_aggregate(indices, b_indices, comp_type, is_unc, expn); else if (N_KIND(expn) == as_string_literal) { if (tup_size(b_indices) != 1) { #ifdef ERRNUM errmsgn(301, 292, expn); #else errmsg("Invalid use of literal in aggregate", "4.3.2", expn); #endif return; } complete_string_literal(expn, comp_type); N_TYPE(expn) = (Symbol) 0; /* clear as no type defined here */ } else if (N_KIND(expn) == as_parenthesis) { /* Context of subaggregate is unconstrained, "others" choice is not*/ /* allowed.*/ expn2 = N_AST1(expn); complete_component(indices, b_indices, comp_type, TRUE, expn2); } else { #ifdef ERRNUM errmsgn(302, 292, expn); #else errmsg("Expect aggregate for component of multidimensional aggregate", "4.3.2", expn); #endif } } void complete_string_literal(Node node, Symbol comp) /*;complete_string_literal*/ { /* String literals can appear as aggregates for arrays of character type. * We have to verify that each character in the string is an enumeration * literal for that type. */ char *strg, c, *lit; Tuple arr, lit_map; Node lo, hi; Symbol sc; int i, strglen, istr, ilitmap, v, exists, found; strg = N_VAL(node); sc = SCOPE_OF(comp); if (!tup_mem((char *)sc, open_scopes) && !tup_mem((char *)sc, used_mods)) { #ifdef ERRNUM errmsgn(303, 304, node); #else errmsg("characters in a string literal must be directly visible", "4.2(3)", node); #endif } if (comp == symbol_character || comp == symbol_any) { /*arr := [abs c: c in strg];*/ strglen = strlen(strg); arr = tup_new(strglen); for (i = 1; i <= strglen; i++) arr[i] = (char *) strg[i-1]; N_VAL(node) = (char *) arr; N_KIND(node) = as_string_ivalue; } else {/* Some enumeration type. Use its literal map.*/ if (NATURE(base_type(comp)) != na_enum) { #ifdef ERRNUM errmsgn(305, 251, node); #else errmsg("Component type of context is not a character type", "4.2", node); #endif return; } lit_map = (Tuple) literal_map(base_type(comp)); if (lit_map == (Tuple)0) lit_map = tup_new(0); /* arr := [lit_map('''' + c + '''') : c in strg]; */ strglen = strlen(strg); arr = tup_new(strglen); lit = emalloct(4, "complete-string-literal"); exists = FALSE; for (istr = 0; c = strg[istr]; istr++) { lit[0] = lit[2] = '\''; lit[1] = c; lit[3] = '\0'; found = FALSE; for (ilitmap = 1; ilitmap < tup_size(lit_map); ilitmap += 2) { if (streq(lit, lit_map[ilitmap])) { arr[istr+1] = lit_map[ilitmap+1]; found = TRUE; break; } } if (!found) exists = TRUE; } /* if exists c = strg(i) | arr(i) = om then */ /* Some characters are not in the component type. */ if (exists) { create_raise(node, symbol_constraint_error); return; } else { /* The individual characters must be bounds-checked as any other * array component. */ N_VAL(node) = (char *)arr; N_KIND(node) = as_string_ivalue; if (NATURE(comp) == na_subtype) { lo = (Node) (SIGNATURE(comp))[2]; hi = (Node) (SIGNATURE(comp))[3]; if (is_static_expr(lo) && is_static_expr(hi)) { /* and exists v in arr | v<N_VAL(lo) or v>N_VAL(hi) then */ for (istr = 1; istr <= strglen; istr++) { v = (int) arr[istr]; if (v < ((Const)N_VAL(lo))->const_value.const_int || v > ((Const)N_VAL(hi))->const_value.const_int) { create_raise(node, symbol_constraint_error); return; } } } } } } } void complete_r_aggregate(Symbol aggregate_type, Node expn) /*;complete_r_aggregate*/ { /* Perform resolution of components in a record aggregate. If the * record type has discriminants, we must first resolve the discriminant * components, in order to determine the variant parts to which the rest * of the aggregate must conform. */ Tuple arg_list, ttup, btup; Tuple discr_list; int first_named, exists, ctupi, num_discr; Tuple positional_args; Tuple named_args; int discri; Node comp_assoc, choice_list, choice_node, e, c_expr, others_expr; Tuple discr_map, all_component_names; int i1, found_discr_val; char *sel; Node simple_name, others_comp_list, lnode; Symbol discr, bs, ctupd, btype; Node invariant_node, variant_node, ctupn; Declaredmap sel_names; Tuple leftovers; Node discr_id, variant_list, alt; int discr_value, lo, hi; Tuple case_list; Node case_node, component_list, list_node; Tuple comp_assoc_list; int comp_pos, i, j, k; Tuple choices, components_seen; /* sel : IDENTIFIER;*/ Symbol selector; Fortup ft1, ft2; int found_discr_value; if (cdebug2 > 3) TO_ERRFILE("AT PROC : complete_r_aggregate:"); /* In SETL, components_seen is a set of symbols. Here we keep it as * tuple. Since it is a local variable, we allocate it here and free * it before every return from this procedure. */ components_seen = tup_new(0); arg_list = N_LIST(expn); discr_list = (Tuple) discriminant_list(aggregate_type); num_discr = tup_size(discr_list); /* Components can be given by named choices. Divide argument list * into positional and named components . */ exists = FALSE; FORTUPI(comp_assoc = (Node), arg_list, i, ft1); if (N_KIND(comp_assoc) == as_choice_list) { exists = TRUE; break; } ENDFORTUP(ft1); if (exists) first_named = i; else first_named = tup_size(arg_list) + 1; /* TBSL: positional_args and named_args may not have to be built * as separate tuples; if they are, should free on return * Also check that don't get into nasty boundary cases here * (building tuple of length -1, etc. */ positional_args = tup_new(first_named-1); for (j = 1; j <= first_named-1; j++) positional_args[j] = arg_list[j]; /*named_args = arg_list(first_named..);*/ named_args = tup_new(tup_size(arg_list)-first_named+1); k = 1; for (j = first_named; j <= tup_size(arg_list); j++) named_args[k++] = arg_list[j]; others_expr = (Node) 0; FORTUP(comp_assoc = (Node), named_args, ft1); choice_list = N_AST1(comp_assoc); c_expr = N_AST2(comp_assoc); exists = FALSE; FORTUP(choice_node = (Node), N_LIST(choice_list), ft2); if (N_KIND(choice_node) == as_others_choice) { exists = TRUE; break; } ENDFORTUP(ft2); if (exists) { if (tup_size( N_LIST(choice_list)) != 1 || (comp_assoc != (Node)named_args[tup_size(named_args)])) { #ifdef ERRNUM errmsgn(306, 294, choice_node); #else errmsg("OTHERS must appear alone and last in a choice list", "4.3", choice_node); #endif tup_free(components_seen); return; } else { others_expr = c_expr; break; } } ENDFORTUP(ft1); discr_map = tup_new(0); if (num_discr > 0) { /* add value for 'constrained' bit, and do not check for it later.*/ e = new_ivalue_node(int_const(TRUE), symbol_boolean); copy_span((Node)arg_list[1], e); discr_map = discr_map_put(discr_map, symbol_constrained, e); } /* Map the discriminants into the (hopefully) static expressions * given for them. Omit constrained bit from consideration. */ i1 = num_discr == 0 ? 0: (num_discr -1 < tup_size(positional_args) ? num_discr -1 : tup_size(positional_args)); /* collect the positional discriminants first. */ for (i = 1; i <= i1; i++) { comp_assoc = (Node) positional_args[i]; discr_map = discr_map_put(discr_map, (Symbol) discr_list[i+1], comp_assoc); } /* Now look for named discriminants among named components.*/ for (i = i1 + 2; i <= num_discr; i++) { discr = (Symbol) (discr_list[i]); found_discr_val = FALSE; FORTUP(comp_assoc = (Node), named_args, ft1); choice_list = N_AST1(comp_assoc); c_expr = N_AST2(comp_assoc); FORTUP(choice_node = (Node), N_LIST(choice_list), ft2); if (N_KIND(choice_node) == as_choice_unresolved) { simple_name = N_AST1(choice_node); if (streq(N_VAL(simple_name), original_name(discr))) { found_discr_val = TRUE; goto endforcomp; } } ENDFORTUP(ft2); ENDFORTUP(ft1); endforcomp: if (found_discr_val) discr_map = discr_map_put(discr_map, discr, c_expr); else if (others_expr != (Node)0) discr_map = discr_map_put(discr_map, discr, copy_tree(others_expr)); else { #ifdef ERRNUM id_errmsgn(307, discr, 308, expn); #else errmsg_id("No value supplied for discriminant %", discr, "4.3.1", expn); #endif tup_free(components_seen); return; } } /* perform type resolution on the associations for discriminants */ for (discri = 1; discri <= tup_size(discr_map); discri += 2) { discr = (Symbol) discr_map[discri]; c_expr = (Node) discr_map[discri+1]; if (N_TYPE(c_expr) == (Symbol)0) check_type(TYPE_OF(discr), c_expr); } invariant_node = (Node) invariant_part(aggregate_type); variant_node = (Node)(variant_part(aggregate_type)); sel_names = (Declaredmap) declared_components(aggregate_type); /* Now assemble the list of selector names. Each component declara- * tion declares a list of selectors with the same type. */ all_component_names = build_comp_names(invariant_node); /* Scan the variant part of the record declaration, and collect the * types corresponding to the given discriminants. */ while (variant_node != OPT_NODE) { found_discr_value = FALSE; discr_id = N_AST1(variant_node); variant_list = N_AST2(variant_node); c_expr = discr_map_get(discr_map, N_UNQ(discr_id)); /* Verify that a discriminant which governs a variant part*/ /* is static.*/ if (!is_static_expr(c_expr)) { #ifdef ERRNUM nval_errmsgn(309, discr_id, 308, c_expr); #else errmsg_nval("Value for discriminant % must be static", discr_id, "4.3.1", c_expr); #endif /* TBSL: this was N_UNQ, but probably should be N_VAL (gs Sep 20)*/ tup_free(components_seen); return; } discr_value = INTV((Const)N_VAL(c_expr)); case_list = N_LIST(variant_list); case_node = (Node)case_list[tup_size(case_list)]; if (N_KIND(case_node) == as_others_choice) others_comp_list = N_AST2(case_node); else others_comp_list = (Node)0; FORTUP(case_node = (Node), case_list, ft1); choice_list = N_AST1(case_node); component_list = N_AST2(case_node); exists = FALSE; if (N_KIND(case_node) == as_others_choice) continue; FORTUP(alt = (Node), N_LIST(choice_list), ft2); /* find the variant selected by given value of discriminant. * all choices are now discrete ranges. */ lo = INTV((Const)N_VAL(N_AST1(alt))); hi = INTV((Const)N_VAL(N_AST2(alt))); if (lo <= discr_value && discr_value <= hi) { exists = TRUE; break; } ENDFORTUP(ft2); if (exists) { /* Variants may be nested.*/ invariant_node = N_AST1(component_list); variant_node = N_AST2(component_list); /*all_component_names +:= build_comp_names(invariant_node);*/ btup = build_comp_names(invariant_node); FORTUP(bs = (Symbol), btup, ft1); all_component_names = tup_with(all_component_names, (char *) bs); ENDFORTUP(ft1); tup_free(btup); found_discr_value = TRUE; break /*quit forall case_node*/; } ENDFORTUP(ft1); if (!found_discr_value) { if (others_comp_list != (Node)0) { invariant_node = N_AST1(others_comp_list); variant_node = N_AST2(others_comp_list); btup = build_comp_names(invariant_node); FORTUP(bs = (Symbol), btup, ft1); all_component_names = tup_with(all_component_names, (char *)bs); ENDFORTUP(ft1); tup_free(btup); /*all_component_names +:=build_comp_names(invariant_node);*/ } else { create_raise(expn, symbol_constraint_error); tup_free(components_seen); return; } } } comp_pos = 1; /* Index into list of selector assignments.*/ /*components_seen = tup_new(0); now allocated at start of proc*/ if (cdebug2 > 0) { TO_ERRFILE("record fields are: "); } /* The list of component asssociations is built with pairs name -> expr * for all components present, including discriminants. */ /*comp_assoc_list := [new_comp_assoc(d, v) : [d, v] in discr_map];*/ comp_assoc_list = tup_new(tup_size(discr_map)/2); for (ctupi = 1; ctupi <= tup_size(discr_map); ctupi += 2) { ctupd = (Symbol) discr_map[ctupi]; ctupn = (Node) discr_map[ctupi+1]; comp_assoc_list[(ctupi+1)/2] = (char *) new_comp_assoc(ctupd, ctupn); } /* Perform resolution of all components following the positional * discriminants. Skip over named associations which are discriminants * since these have already been resolved. */ for(i = i1+1; i <= tup_size(arg_list); i++) { comp_assoc = (Node) arg_list[i]; if (N_KIND(comp_assoc) == as_choice_list) { choice_list = N_AST1(comp_assoc); c_expr = N_AST2(comp_assoc); choices = tup_new(0); FORTUP(choice_node = (Node), N_LIST(choice_list), ft1); if (N_KIND(choice_node) == as_choice_unresolved) { simple_name = N_AST1(choice_node); sel = N_VAL(simple_name); current_node = simple_name; check_void(sel); selector = dcl_get(sel_names, sel); if (selector == (Symbol)0) { #ifdef ERRNUM errmsgn(310, 308, simple_name); #else errmsg("Undefined component name","4.3.1", simple_name); #endif tup_free(components_seen); return; } choices = tup_with(choices, (char *) selector); if (tup_mem((char *)selector, components_seen)) { #ifdef ERRNUM errmsgn(311, 308, simple_name); #else errmsg("Duplicate value for component in aggregate", "4.3.1", simple_name); #endif tup_free(components_seen); return; } else { if (!tup_mem((char *)selector, components_seen)) components_seen = tup_with(components_seen, (char *)selector); if (NATURE(selector) != na_discriminant) { if (tup_size(N_LIST(choice_list))> 1) /* copy expression node for each choice.*/ e = copy_tree(c_expr); else e = c_expr; resolve_r_component(e, selector, discr_map); comp_assoc_list = tup_with(comp_assoc_list, (char *)new_comp_assoc(selector, e)); } comp_pos += 1; } } else if (N_KIND(choice_node) == as_simple_choice) { #ifdef ERRNUM errmsgn(312, 308, choice_node); #else errmsg("choice in record aggregate must be selector name", "4.3.1", choice_node); #endif tup_free(components_seen); return; } else if (N_KIND(choice_node) == as_range_choice) { #ifdef ERRNUM errmsgn(313, 308, choice_node); #else errmsg("Range choice not allowed in record aggregate", "4.3.1", choice_node); #endif tup_free(components_seen); return; } else if (N_KIND(choice_node) == as_others_choice) { leftovers = tup_new(0); FORTUP(selector = (Symbol), all_component_names, ft2); if (!tup_mem((char *)selector, components_seen)) { if (!tup_mem((char *) selector, leftovers)) leftovers=tup_with(leftovers, (char *)selector); } ENDFORTUP(ft2); if (tup_size( leftovers) == 0) { #ifdef ERRNUM l_errmsgn(314, 315, 308, choice_node); #else errmsg_l("OTHERS choice must represent at least ", "one component", "4.3.1", choice_node); #endif tup_free(components_seen); return; } else { FORTUP(selector = (Symbol), leftovers, ft2); if(! tup_mem((char *)selector, components_seen)) components_seen = tup_with(components_seen, (char *) selector); if (NATURE(selector) != na_discriminant) { if (tup_size(leftovers)> 1) { /* copy expression node.*/ e = copy_tree(c_expr); } else { e = c_expr; } resolve_r_component(e, selector, discr_map); if (N_TYPE(c_expr) == symbol_any) { #ifdef ERRNUM id_errmsgn(316, selector, 308, choice_node); #else errmsg_id( "OTHERS expression incompatible with %", selector, "4.3.1", choice_node); #endif tup_free(components_seen); return; } comp_assoc_list = tup_with(comp_assoc_list, (char *)new_comp_assoc(selector, e)); } choices = tup_with(choices, (char *) selector); ENDFORTUP(ft2); } } ENDFORTUP(ft1); ttup= tup_new(0); FORTUP(selector = (Symbol), choices, ft2); btype = base_type(TYPE_OF(selector)); if (!tup_mem((char *) btype, ttup)) ttup = tup_with(ttup, (char *) btype); ENDFORTUP(ft2); if (tup_size(ttup) > 1) { #ifdef ERRNUM errmsgn(317, 308, choice_list); #else errmsg("components on a choice list must have same type", "4.3.1", choice_list); #endif } tup_free(ttup); } else { /* Positional record aggregate. */ if (comp_pos > tup_size(all_component_names)) { #ifdef ERRNUM errmsgn(318, 10, expn); #else errmsg("Too many components for record aggregate","none", expn); #endif tup_free(components_seen); return; } selector = (Symbol) all_component_names[comp_pos]; resolve_r_component(comp_assoc, selector, discr_map); comp_pos += 1; if (!tup_mem((char *) selector, components_seen)) components_seen = tup_with(components_seen, (char *) selector); comp_assoc_list = tup_with(comp_assoc_list, (char *) new_comp_assoc(selector, comp_assoc)); } } exists = FALSE; FORTUP(selector = (Symbol), all_component_names, ft1); if (!tup_mem((char *) selector, components_seen)) { exists = TRUE; break; } ENDFORTUP(ft1); if (exists) { #ifdef ERRNUM id_errmsgn(319, selector, 308, current_node); #else errmsg_id("No value supplied for component %", selector, "4.3.1", current_node); #endif tup_free(components_seen); return; } for (i = 1; i <= tup_size(comp_assoc_list); i++) { if (N_KIND(N_AST2((Node)comp_assoc_list[i])) == as_raise) { create_raise(expn, symbol_constraint_error); return; } } N_UNQ(expn) = sym_new(na_void); N_KIND(expn) = as_record_aggregate; N_LIST(expn) = (Tuple)0; /* clear out n_list */ list_node = node_new(as_list); N_LIST(list_node) = comp_assoc_list; lnode = node_new(as_aggregate_list); N_AST1(lnode) = list_node; N_AST2(lnode) = OPT_NODE; N_AST1(expn) = lnode; N_AST2(expn) = OPT_NODE; } static Node new_comp_assoc(Symbol selector, Node expn) /*;new_comp_assoc*/ { /* Used to normalize the representation of record aggregates: associate * a selector name with the expression given for it in the aggregate. */ Node c_node; c_node = node_new(as_record_choice); N_AST1(c_node) = new_name_node(selector); N_AST2(c_node) = expn; copy_span(expn, N_AST1(c_node)); return c_node; } Tuple build_comp_names(Node invariant_node) /*;build_comp_names*/ { /* Collect names of record components in the invariant part of the * record. Skip nodes generated for internal anonymous types. */ Tuple all_component_names; Node node, id_list_node, id_node; Fortup ft1, ft2; if (cdebug2 > 3) TO_ERRFILE("AT PROC : build_comp_names"); all_component_names = tup_new(0); FORTUP(node = (Node), N_LIST(invariant_node), ft1); if (N_KIND(node) == as_subtype_decl || N_KIND(node) == as_delayed_type) continue; id_list_node = N_AST1(node); FORTUP(id_node = (Node), N_LIST(id_list_node), ft2); /* test against 0 needed since in SETL om added at end of tuple * has no effect! ds 14 aug * Skip over 'constrained' bit added by code generator (case of a * separately compiled record type definition. */ if (N_UNQ(id_node) != (Symbol)0) all_component_names = tup_with(all_component_names, (char *) N_UNQ(id_node)); ENDFORTUP(ft2); ENDFORTUP(ft1); return all_component_names; } static void resolve_r_component(Node e, Symbol selector, Tuple discr_map) /*;resolve_r_component.*/ { Symbol comp_type; resolve1(e); if (!noop_error) { comp_type = TYPE_OF(selector); /* if its bounds depend on discriminants, we emit subtypes with * the actual values of the discriminants given in the aggr. */ comp_type = check_discriminant_dependence(comp_type, discr_map); res2_check(e, comp_type); } } static Symbol check_discriminant_dependence(Symbol comp_type, Tuple discr_map) /*;check_discriminant_dependence*/ { /* if the subtype indication of a record component depends on a * discriminant, then the expression in a record aggregate that corresponds * to this component is given a subtype that is constrained by the values * of the discriminants that appear in the aggregate itself. */ Tuple constraint, new_constraint, tup, new_indices; Node ubd, lbd, e; Symbol d, type_name, index, new_index, new_type, new_acc; Tuple comp_discr_map, new_discr_map; int i, newi, new_t; Fortup ft1; if (tup_size(discr_map) == 0) return comp_type; type_name = (is_access(comp_type)) ? (Symbol)designated_type(comp_type): comp_type; if (is_array(type_name)) { tup = index_types(type_name); new_indices = tup_new(0); FORTUP(index = (Symbol), tup, ft1) constraint = SIGNATURE(index); lbd = (Node)constraint[2]; ubd = (Node)constraint[3]; newi = FALSE; if (N_KIND(lbd) == as_discr_ref) { lbd = discr_map_get(discr_map, N_UNQ(lbd)); newi = TRUE; } if (N_KIND(ubd) == as_discr_ref) { ubd = discr_map_get(discr_map, N_UNQ(ubd)); newi = TRUE; } if (newi) { new_index = sym_new(na_subtype); dcl_put(DECLARED(scope_name), str_newat(), new_index); new_constraint = constraint_new(CONSTRAINT_RANGE); new_constraint[2] = (char *)lbd; new_constraint[3] = (char *)ubd; TYPE_OF(new_index) = TYPE_OF(index); SIGNATURE(new_index) = new_constraint; SCOPE_OF(new_index) = scope_name; ALIAS (new_index) = ALIAS(index); new_indices = tup_with(new_indices, (char *)new_index); new_t = TRUE; } else new_indices = tup_with(new_indices, (char *)index); ENDFORTUP(ft1); if (new_t) { /* create new subtype of array type, using new index types, and * label aggregate with this new array subtype. */ new_type = sym_new(na_subtype); dcl_put(DECLARED(scope_name), str_newat(), new_type); TYPE_OF(new_type) = base_type(type_name); SIGNATURE(new_type) = tup_new(2); SIGNATURE(new_type)[1] = (char *)new_indices; SIGNATURE(new_type)[2] = (char *)component_type(type_name); SCOPE_OF(new_type) = scope_name; ALIAS(new_type) = ALIAS(type_name); } else { tup_free(new_indices); return comp_type; } } else if (NATURE(type_name) == na_subtype && is_record(type_name)) { /* see if any discriminant constraint is itself given by a discrimi- * nant (which must be a discriminant of the enclosing record. */ comp_discr_map = (Tuple)numeric_constraint_discr(SIGNATURE(type_name)); new_discr_map = tup_new(0); newi = FALSE; for (i = 1; i <= tup_size(comp_discr_map); i += 2) { d = (Symbol)comp_discr_map[i]; e = (Node) comp_discr_map[i+1]; if (N_KIND(e) == as_discr_ref) { /* replace discriminant reference with value given in enclosing * aggregate. */ newi = TRUE; new_discr_map = discr_map_put(new_discr_map, d, copy_tree(discr_map_get(discr_map, N_UNQ(e)))); } else new_discr_map = discr_map_put(new_discr_map, d, e); } if (newi) { new_type = sym_new(na_subtype); dcl_put(DECLARED(scope_name), str_newat(), new_type); tup = constraint_new(CONSTRAINT_DISCR); numeric_constraint_discr(tup) = (char *)new_discr_map; TYPE_OF(new_type) = TYPE_OF(type_name); SIGNATURE(new_type) = tup; OVERLOADS(new_type) = OVERLOADS(type_name); SCOPE_OF(new_type) = scope_name; ALIAS(new_type) = ALIAS(type_name); } else { tup_free(new_discr_map); return comp_type; } } else { /* cannot be a discriminant constraint.*/ return comp_type; } if (is_access(comp_type)) { /* create access type to new constrained array type.*/ new_acc = sym_new(na_subtype); dcl_put(DECLARED(scope_name), str_newat(), new_acc); TYPE_OF(new_acc) = TYPE_OF(comp_type); SIGNATURE(new_acc) = constraint_new(CONSTRAINT_ACCESS); SIGNATURE(new_acc)[2] = (char *)new_type; /*designated type*/ SCOPE_OF(new_acc) = scope_name; ALIAS(new_acc) = ALIAS(comp_type); return new_acc; } else return new_type; } void valid_task_name(Node task_name) /*;valid_task_name*/ { /* First pass over an expression that must yield a task type: called to * resolve entry names. */ Set task_types; Forset fs1; Symbol t; if (cdebug2 > 3) TO_ERRFILE("AT PROC : valid_task_name"); resolve1(task_name); task_types = set_new(0); FORSET(t = (Symbol), N_PTYPES(task_name), fs1); if (is_task_type(t) || (is_access(t) && is_task_type(designated_type(t)))) task_types = set_with(task_types, (char *) t); ENDFORSET(fs1); if (set_size(task_types) == 0) { #ifdef ERRNUM errmsgn(320, 321, task_name); #else errmsg("expect task name ", "9.5", task_name); #endif } N_PTYPES(task_name) = task_types; } void complete_task_name(Node task1, Symbol context_typ) /*;complete_task_name*/ { /* Complete resolution of task name used in an entry name.The context_typ * is obtained from the scope of the resolved entry name. Derived task * types have the same entries as their root type, and the unique type of * the task name is thus the one whose root type is the context type. */ Node a_task; Set types; Symbol t, tmp; int exists; Forset fs1; Symbol t_n; if (cdebug2 > 3) TO_ERRFILE("AT PROC : complete_task_name"); types = N_PTYPES(task1); exists = FALSE; FORSET(t = (Symbol), types, fs1); if (root_type(t) == context_typ) { exists = TRUE; break; } ENDFORSET(fs1); if (exists) { resolve2(task1, t); if (N_KIND(task1) != as_simple_name) eval_static(task1); } else { exists = FALSE; FORSET(t = (Symbol), types, fs1); tmp = (Symbol) designated_type(t); if (is_access(t) && root_type(tmp) == context_typ) { exists = TRUE; break; } ENDFORSET(fs1); if (exists) { resolve2(task1, t); if (N_KIND(task1) != as_simple_name) eval_static(task1); a_task = copy_node(task1); N_KIND(task1) = as_all; /* explicit dereference*/ N_AST1(task1) = a_task; /* of access to task*/ N_AST2(task1) = N_AST3(task1) = N_AST4(task1) = (Node) 0; N_TYPE(task1) = (Symbol) designated_type(t); } else { /* previous error.*/ return; } } /* Within the task body a task type designates the object currently exe- * cuting that task. We replace the task type with what will be its * run-time identity. */ t_n = N_UNQ(task1); if (N_KIND(task1) == as_simple_name && is_task_type(t_n)) { if (in_open_scopes(t_n)) N_UNQ(task1) = dcl_get(DECLARED(t_n), "current_task"); else { /* Use of the task type otherwise is invalid.*/ #ifdef ERRNUM errmsgn(322, 323, task1); #else errmsg("invalid use of task type outside of its own body", "9.1", task1); #endif } } } void res2_check(Node expn2, Symbol context_type) /*;res2_check*/ { /* Called to impose constraints when needed, on aggregate components * and allocated objects. These are non-sliding contexts for aggregates. */ int may_others; if (cdebug2 > 3) TO_ERRFILE("AT PROC : res2_check"); may_others = full_others; full_others = TRUE; resolve2(expn2, context_type); apply_constraint(expn2, context_type); full_others = may_others; if (!noop_error) eval_static(expn2); } Symbol attribute_type(int attribute, Symbol typ, Node arg1, Node arg2) /*;attribute_type*/ { /* -attribute- is a predefined attribute. arg1 is the first arg, * whose type is typ, and arg2 is the second argument (or a dummy 1). * The result type of an attribute is either a numeric type, or * the type of its first argument ( attributes of enumerations). * FIRST and LAST are more complicated : they return the first * value of the index type of the i'th dimension of their first * argument. * For enumeration types, FIRST and LAST simply return the type * of the first argument. */ Symbol n; Set types2; int dim; Symbol a_type, root, t, t2; int type_ok, exists; Forset fs1; Unitdecl ud; if (cdebug2 > 3) TO_ERRFILE("AT PROC : attribute_type"); n = N_UNQ(arg2); if ((N_KIND(arg2) == as_simple_name) && (n != (Symbol)0)) N_PTYPES(arg2) = set_new1((char *) TYPE_OF(n)); else resolve1(arg2); /* Begin resolution of second arg*/ types2 = N_PTYPES(arg2); if (types2 == (Set)0) types2 = set_new(0); if (set_size(types2) == 0) /* Some type error .*/ return symbol_any; if ( attribute == ATTR_O_FIRST || attribute == ATTR_T_FIRST || attribute == ATTR_O_LAST || attribute == ATTR_T_LAST || attribute == ATTR_O_RANGE || attribute == ATTR_T_RANGE || attribute == ATTR_O_LENGTH || attribute == ATTR_T_LENGTH) { /* The second argument must be a universal integer, and * and must be static. Complete its resolution now. */ if (set_mem((char *) symbol_universal_integer, types2)) { resolve2(arg2, symbol_universal_integer); specialize(arg2, symbol_integer); } else pass1_error_str("index number of attribute % must be universal", attribute_str(attribute), "Appendix A", arg2); if (! is_static_expr(arg2) || N_KIND(arg2) != as_ivalue || ((Const)N_VAL(arg2))->const_kind != CONST_INT) { pass1_error_str("Second argument of % must be static integer", attribute_str(attribute), "3.6.2", arg2); /* ?? */ dim = 1; /* assume 1*/ } else dim = INTV((Const)N_VAL(arg2)); a_type = typ; if (is_array(typ)) { if (is_type_node(arg1) && can_constrain(N_UNQ(arg1))) { pass1_error_str("Unconstrained array type for attribute %", attribute_str(attribute), "3.6.2", arg1); return symbol_any; } if ( (dim > no_dimensions(typ)) || (dim < 1)) { pass1_error_l("Invalid dimension number for array type", " in attribute", "3.6.2", arg1); return symbol_any; } if (attribute == ATTR_O_LENGTH || attribute == ATTR_T_LENGTH) a_type = symbol_universal_integer; else { /* Get type of index for specified dimension.*/ a_type = (Symbol) index_types(a_type)[dim]; } } } else if (attribute == ATTR_ADDRESS) { ud = unit_decl_get("spSYSTEM"); if (ud == (Unitdecl)0 || !in_vis_mods(ud->ud_unam)) { /* The use of this attribute seems incorrect if its type * cannot be named. */ #ifdef ERRNUM errmsgn(324, 325, arg1); #else errmsg("use of SYSTEM.ADDRESS requires presence of package SYSTEM", "13.7.2, Annex A", arg1); #endif a_type = symbol_integer; /* Closest thing we've got.*/ } else { /*a_type = ??visible('SYSTEM')('ADDRESS');*/ a_type = dcl_get_vis(DECLARED(ud->ud_unam), "ADDRESS"); } } else if (attribute != ATTR_BASE && attribute != ATTR_T_FIRST && attribute != ATTR_O_FIRST && attribute != ATTR_O_LAST && attribute != ATTR_T_LAST && attribute != ATTR_PRED && attribute != ATTR_O_RANGE && attribute != ATTR_T_RANGE && attribute != ATTR_SUCC && attribute != ATTR_VAL && attribute != ATTR_VALUE) { /*a_type = TYPE_OF(attribute);*/ if ( attribute == ATTR_AFT || attribute == ATTR_COUNT || attribute == ATTR_DIGITS || attribute == ATTR_EMAX || attribute == ATTR_FIRST_BIT || attribute == ATTR_FORE || attribute == ATTR_LAST_BIT || attribute == ATTR_LAST_BIT || attribute == ATTR_O_LENGTH || attribute == ATTR_T_LENGTH || attribute == ATTR_MACHINE_EMAX || attribute == ATTR_MACHINE_EMIN || attribute == ATTR_MACHINE_MANTISSA || attribute == ATTR_MACHINE_RADIX || attribute == ATTR_MANTISSA || attribute == ATTR_POS || attribute == ATTR_POSITION || attribute == ATTR_SAFE_EMAX || attribute == ATTR_O_SIZE || attribute == ATTR_T_SIZE || attribute == ATTR_STORAGE_SIZE || attribute == ATTR_WIDTH) { a_type = symbol_universal_integer; } else if (attribute == ATTR_DELTA || attribute == ATTR_EPSILON || attribute == ATTR_LARGE || attribute == ATTR_SMALL || attribute == ATTR_SAFE_LARGE || attribute == ATTR_SAFE_SMALL) { a_type = symbol_universal_real; } else if (attribute==ATTR_O_CONSTRAINED || attribute==ATTR_T_CONSTRAINED || attribute == ATTR_MACHINE_OVERFLOWS || attribute == ATTR_MACHINE_ROUNDS || attribute == ATTR_CALLABLE || attribute == ATTR_TERMINATED) { a_type = symbol_boolean; } else if (attribute == ATTR_IMAGE) a_type = symbol_string; } else if (attribute == ATTR_BASE || attribute == ATTR_POS || attribute == ATTR_PRED || attribute == ATTR_SUCC || attribute == ATTR_VAL || attribute == ATTR_VALUE) { a_type = base_type(typ); } else { a_type = typ; } root = root_type(typ); /* Now verify that the type of the argument is valid for the attribute.*/ t = N_UNQ(arg1); if (t != (Symbol)0 && tup_mem((char *) t, open_scopes) && NATURE(t) == na_record) { #ifdef ERRNUM id_errmsgn(206, t, 207, arg1); /* ?? */ #else errmsg_id("Invalid self-reference in definition of %", t, "3.1", arg1); /* ?? */ #endif return symbol_any; } if (attribute == ATTR_ADDRESS) type_ok = !is_type_node(arg1); else if (attribute == ATTR_BASE) type_ok = is_type(root); else if (attribute == ATTR_T_FIRST || attribute == ATTR_O_FIRST || attribute == ATTR_O_LAST || attribute == ATTR_T_LAST) type_ok = is_scalar_type(root) || is_array(root); else if (attribute == ATTR_VALUE) { if (!is_discrete_type(root)) type_ok = FALSE; else { exists = FALSE; FORSET(t2 = (Symbol), types2, fs1); if (compatible_types(symbol_string, t2)) { exists = TRUE; break; } ENDFORSET(fs1); type_ok = exists; } } else if (attribute == ATTR_IMAGE || attribute == ATTR_POS || attribute == ATTR_PRED || attribute == ATTR_SUCC) { if (! is_discrete_type(root)) type_ok = FALSE; else { exists = FALSE; FORSET(t2 = (Symbol), types2, fs1); if (compatible_types(typ, t2)) { exists = TRUE; break; } ENDFORSET(fs1); type_ok = exists; } } else if (attribute == ATTR_VAL) { if (!is_discrete_type(root)) type_ok = FALSE; else { exists = FALSE; FORSET(t2 = (Symbol), types2, fs1); if (is_integer_type(root_type(t2))) { exists = TRUE; break; } ENDFORSET(fs1); type_ok = exists; } } else if (attribute == ATTR_AFT || attribute == ATTR_DELTA || attribute == ATTR_FORE) { type_ok = is_fixed_type(root); } else if (attribute == ATTR_DIGITS || attribute == ATTR_EMAX || attribute == ATTR_EPSILON || attribute == ATTR_MACHINE_RADIX || attribute == ATTR_MACHINE_MANTISSA || attribute == ATTR_MACHINE_EMAX || attribute == ATTR_MACHINE_EMIN || attribute == ATTR_SAFE_EMAX) { type_ok = root == symbol_float; } else if (attribute == ATTR_LARGE || attribute == ATTR_MACHINE_ROUNDS || attribute == ATTR_MACHINE_OVERFLOWS || attribute == ATTR_MANTISSA || attribute == ATTR_SMALL || attribute == ATTR_SAFE_LARGE || attribute == ATTR_SAFE_SMALL) { if (is_fixed_type(root) || root == symbol_float) type_ok = TRUE; else type_ok = FALSE; } else if (attribute == ATTR_O_LENGTH || attribute == ATTR_T_LENGTH || attribute == ATTR_O_RANGE || attribute == ATTR_T_RANGE) type_ok = is_array(root); else if (attribute==ATTR_O_CONSTRAINED || attribute == ATTR_T_CONSTRAINED) { if (is_type_node(arg1)) type_ok = is_private(typ); else if ( is_record(root) && has_discriminants(root)) type_ok = TRUE; else type_ok = FALSE; } else if (attribute == ATTR_TERMINATED || attribute == ATTR_CALLABLE) { if (is_access(root)) root = (Symbol) designated_type(root); type_ok = is_task_type(root); } else if (attribute == ATTR_STORAGE_SIZE) type_ok = (is_task_type(root) || is_access(root)); else if (attribute == ATTR_WIDTH) type_ok = is_discrete_type(root); else if (attribute == ATTR_COUNT || attribute == ATTR_FIRST_BIT || attribute == ATTR_LAST_BIT || attribute == ATTR_O_SIZE || attribute == ATTR_T_SIZE || attribute == ATTR_POSITION) { type_ok = TRUE; } else { #ifdef ERRNUM str_errmsgn(326, attribute_str(attribute), 233, arg1); #else errmsg_str("Undefined attribute: %", attribute_str(attribute), "Annex A", arg1); #endif a_type = symbol_any; type_ok = TRUE; } if (type_ok) return a_type; else { pass1_error_str("Invalid argument type for attribute %", attribute_str(attribute), "Annex A", arg1); return symbol_any; } } int compatible_types(Symbol t_out, Symbol t_in) /*;compatible_types*/ { /* This procedure verifies that an expression of type -t_in- can appear * in a context requiring type -t_out-. In the case of subtypes this * procedure indicates whether a run-time check will be necessary. * Equality, set and comparison operators carry a special type-marker which * is ignored on the first pass of type resolution, because the type of * the arguments of these operators have no effect on the result type. * On the second pass, these special type-markers are used to indicate * the need for a consistency check among the types of the two actual * parameters themselves. */ Symbol r; int n; Symbol tmp; if (cdebug2 > 0) { TO_ERRFILE("check compatible types "); printf(" %s %s\n", ((t_out != (Symbol)0) ? ORIG_NAME(t_out): ""), ((t_in != (Symbol) 0)? ORIG_NAME(t_in) : "")); } if (t_in == (Symbol)0 || t_out == (Symbol)0 /* syntax error*/ || (t_in == t_out) /*compatible types*/ || in_multiple_types(t_in) || in_multiple_types(t_out)) { return TRUE; } /* The generic types 'universal_integer', 'universal_real', 'string_type' * and '$FIXED' are used to indicate the type of the corresponding literals. * These types are compatible with specific types of the same family. * On the other hand, the generic 'universal_fixed' is incompatible * with all types, and its presence in any type checking will trigger an * error message, at some point. * To avoid checking for their presence on both sides, we perform the * following normalization : */ if (!in_gen_types(t_in) && in_gen_types(t_out)) { tmp = t_in; t_in = t_out; t_out = tmp; } if (t_in == symbol_universal_integer) return ( root_type(t_out) == symbol_integer); else if(t_in == symbol_universal_real) return (root_type(t_out) == symbol_float || (t_out != symbol_universal_fixed && is_fixed_type(root_type(t_out)))); else if (t_in == symbol_universal_type) return in_univ_types(t_out); else if (t_in == symbol_dfixed) return (t_out == symbol_universal_real || is_fixed_type(t_out)); else if (t_in == symbol_boolean_type) return (root_type(t_out) == symbol_boolean || (is_array(t_out) && root_type((Symbol) component_type(t_out)) == symbol_boolean)); else if (t_in == symbol_discrete_type) return( is_discrete_type(t_out)); else if(t_in == symbol_integer_type) return (root_type(t_out) == symbol_integer || t_out == symbol_universal_integer); else if (t_in == symbol_real_type) { r = root_type(t_out); return (r == symbol_float || (r != symbol_universal_fixed && is_fixed_type(r)) || r == symbol_universal_real); } else if(t_in == symbol_string_type) return (is_array(t_out) && no_dimensions(t_out) == 1 && is_character_type(component_type(t_out))); else if(t_in == symbol_character_type) return(is_character_type(t_out)); else if (t_in == symbol_array_type) return(is_array(t_out)); else if (t_in == symbol_composite_type) { n = NATURE(root_type(t_out)); return(n == na_array || n == na_record); } else if(t_in == symbol_universal_fixed) return FALSE; else /* name equivalence of base types holds for everything else.*/ return (base_type(t_in) == base_type(t_out)); } static int in_gen_types(Symbol t) /*;in_gen_types*/ { return ( t == symbol_array_type || t == symbol_boolean_type || t == symbol_character_type || t == symbol_composite_type || t == symbol_discrete_type || t == symbol_dfixed || t == symbol_integer_type || t == symbol_real_type || t == symbol_string_type || t == symbol_universal_integer || t == symbol_universal_real || t == symbol_universal_fixed || t == symbol_universal_type); } static int in_multiple_types(Symbol t) /*;in_multiple_types*/ { return (t == symbol_equal_type || t == symbol_order_type || t == symbol_any); } void type_error(Set op_names, Symbol typ, int num_types, Node node) /*;type_error*/ { /* Emit error message after a type error was detected during * type resolution. * if num_types > 1, the expression is ambiguous : the operator of * op_names is overloaded, and the argument list is not sufficient to * disambiguate. * If num_types = 0, the argument list is incompatible with the op. */ Symbol op_name; char *op_n; /*TBSL: check type of op_n*/ char *names; int nat; if (cdebug2 > 3) { TO_ERRFILE("AT PROC : type_error"); #ifdef TBSL TO_ERRFILE('opname=' + str op_names); #endif } /* avoid taking set_arb of empty set ds 8 aug */ if (set_size(op_names) == 0) op_name = (Symbol)symbol_undef; /* this should parallel SETL gcs 19 feb * Looks like noop_error should be set (but is not) */ else op_name = (Symbol) set_arb(op_names); op_n = ORIG_NAME(op_name); if (N_KIND(node) == as_simple_name) N_UNQ(node) = op_name; /* to avoid cascaded errors */ if (num_types > 1) { nat = NATURE(op_name); if (nat == na_procedure || nat == na_function || nat == na_procedure_spec || nat == na_function_spec) { #ifdef TBSL names : = +/[original_name(scope_of(x)) + '.' + original_name(x) + ' ' : x in op_names]; #endif names = build_full_names(op_names); #ifdef ERRNUM str_errmsgn(327, names, 328, node); #else errmsg_str("Ambiguous call to one of %", names, "6.6, 8.3", node); #endif } else if (nat == na_op) { #ifdef ERRNUM str_errmsgn(329, op_n, 330, node); #else errmsg_str("Ambiguous operands for %", op_n, "6.7, 8.3", node); #endif } else if (nat == na_literal) { #ifdef ERRNUM str_errmsgn(331, op_n, 332, node); #else errmsg_str("Ambiguous literal: %", op_n, "3.5.1, 4.7, 8.3", node); #endif } else { #ifdef ERRNUM errmsgn(333, 334, node); #else errmsg("ambiguous expression", "8.2, 8.3", node); #endif } /* If the type is ambiguous the expression is of couse invalid.*/ noop_error = TRUE; } else { /* Num_types is zero.*/ if (noop_error) { /* Current expression contained previous error. Do not emit * an aditional one. */ return; } noop_error = TRUE; /* For sure.*/ if (typ == (Symbol) 0) { /* Operator or subprogram .*/ if (strcmp(op_n, "GET") == 0 || strcmp(op_n, "PUT") == 0) { #ifdef ERRNUM errmsgn(335, 336, node); #else errmsg("TEXT_IO not instantiated nor defined for type", "8.4, 14.4", node); #endif } else { if (NATURE(op_name) == na_entry || NATURE(op_name) == na_entry_family) { op_n = "entry call"; } if (NATURE(op_name) == na_op) #ifdef ERRNUM str_errmsgn(337, op_n, 10, node); #else errmsg_str("invalid types for %", op_n, "none", node); #endif else { #ifdef ERRNUM str_errmsgn(338, op_n, 10, node); #else errmsg_str("invalid argument list for %",op_n,"none", node); #endif } } } else if (NATURE(op_name) == na_literal) { #ifdef ERRNUM id_type_errmsgn(339, op_name, typ, 340, node); #else errmsg_id_type("no instance of % has type %", op_name, typ, "3.5.1", node); #endif } else { #ifdef ERRNUM type_errmsgn(341, typ, 10, node); #else errmsg_type("Expect expression to yield type %", typ, "none", node); #endif } } } void premature_access(Symbol type_mark, Node node) /*;premature_access*/ { /* Called when trying to use ( an access to) a fully private type.*/ pass1_error_id("Premature usage of access, private or incomplete type %", type_mark, "7.4.2", node); return; } /* variations of this procedure are defined in errmsg.c */ void pass1_error(char *msg1, char *lrm_sec, Node node) /*;pass1_error*/ { if (cdebug2 > 3) TO_ERRFILE("AT PROC : pass1_error"); /* This procedure is invoked when a type error which requires a special * message is encountered in resolve1. */ if (!noop_error) /* to avoid errmsg prepass */ errmsg(msg1, lrm_sec, node); noop_error = TRUE; /* To avoid cascaded errors.*/ } char *full_type_name(Symbol typ) /*;full_type_name*/ { /* Error message procedure. Restore source name of type, or if anonymous * build some approximate description of its ancestry. */ /* Note that this is only called as part of error message and need ot * be provided until full error messages supported ds 14 aug */ char *type_name; if (cdebug2 > 3) TO_ERRFILE("AT PROC : full_type_name"); type_name = ORIG_NAME(typ); if (type_name == (char *)0 || strlen(type_name) == 0) { /* Anonymous type.*/ /* TBSL: check above line for anonymous vs. undefined */ if ( NATURE(typ) == na_subtype) type_name = full_type_name(TYPE_OF(typ)); else if (NATURE(typ) == na_array) type_name = strjoin(strjoin("array(", full_type_name((Symbol) index_type(typ))), "..."); else if (NATURE(typ) == na_type) /* derived type */ type_name = strjoin("new ", full_type_name(TYPE_OF(typ))); else type_name = strjoin("--anonymous--", ""); } return type_name; } int is_type_node(Node node) /*;is_type_node*/ { return (N_KIND(node) == as_simple_name && (is_type(N_UNQ(node)))); } static int is_integer_type(Symbol sym) /*;is_integer_type*/ { return (sym == symbol_integer || sym == symbol_short_integer || sym == symbol_long_integer || sym == symbol_universal_integer); } static Triplet *triplet_new() { return (Triplet *) emalloct(sizeof(Triplet), "triplet-new"); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.