/* Version 1.0 26/08/1994 Author: Sjaak Smetsers */ #define STATES_GENERATED #define STORE_UNIQUE_ATTRIBUTES_IN_TYPE_NODES #include "compiledefines.h" #include "types.t" #include "system.h" #include "settings.h" #include "syntaxtr.t" #include "comsupport.h" #include "scanner.h" #include "comparser.h" #include "sizes.h" #include "checker.h" #include "transform.h" #include "sa.h" #include "tcsupport.h" #include "typeconv.h" #include "checksupport.h" #include "statesgen.h" #include "buildtree.h" typedef struct attr_ref_count_info { BITVECT arci_used; BITVECT arci_multiply_used; BITVECT arci_implicitly_attributed; struct attr_ref_count_info * arci_next; } * ARC_Info; static ARC_Info CurrentARC_Info; static ARC_Info NewARC_Info (void) { ARC_Info new = CompAllocType (struct attr_ref_count_info); new -> arci_used = ALLBITSCLEAR; new -> arci_multiply_used = ALLBITSCLEAR; new -> arci_implicitly_attributed = ALLBITSCLEAR; new -> arci_next = NULL; return new; } /* NewARC_Info */ static void ClearARC_Info (void) { ARC_Info next; for (next = CurrentARC_Info; next; next = next -> arci_next) { next -> arci_used = ALLBITSCLEAR; next -> arci_multiply_used = ALLBITSCLEAR; next -> arci_implicitly_attributed = ALLBITSCLEAR; } } /* ClearARC_Info */ static void UpdateRefCountInfo (int attr_var, Bool used_implicitly) { ARC_Info attrinfo = CurrentARC_Info; while (attr_var >= 32) { attr_var -= 32; if (attrinfo -> arci_next == NULL) attrinfo -> arci_next = NewARC_Info (); attrinfo = attrinfo -> arci_next; } if (used_implicitly) attrinfo -> arci_implicitly_attributed |= BIT (attr_var); if (BITTEST (attrinfo -> arci_used, attr_var)) attrinfo -> arci_multiply_used |= BIT (attr_var); else attrinfo -> arci_used |= BIT (attr_var); } /* UpdateRefCountInfo */ static Bool DetermineRefCountOfAttributeVarsInTypeVar (TypeNode type_var) { if (type_var -> type_node_attribute >= FirstUniVarNumber) { if (type_var -> type_node_tv != NULL) { if (! TestMark (type_var -> type_node_tv, tv_mark, TV_UNIQUE_VARIABLE_PRINT_MASK)) { SetMark (type_var -> type_node_tv, tv_mark, TV_UNIQUE_VARIABLE_PRINT_MASK); UpdateRefCountInfo (type_var -> type_node_attribute - FirstUniVarNumber, False); } } return True; } else return False; } /* DetermineRefCountOfAttributeVarsInTypeVar */ static BITVECT CombineTypeArguments (ConsVarList cons_var, int arity1, BITVECT args1, int arity2, BITVECT args2) { BITVECT combined_args = ALLBITSCLEAR; int cons_var_arity = cons_var -> cvl_arity; int i, j; for (j = 0; j < cons_var_arity; j++) { BITVECT cons_var_prop = cons_var -> cvl_argclass [j].tac_uniprop; for (i = 0; i < arity1; i++) { if (BITTEST (cons_var_prop, i) && BITTEST (args1, i)) combined_args |= BIT (j); } for (i = 0; i < arity2; i++) { if (BITTEST (cons_var_prop, i+arity1) && BITTEST (args2, i)) combined_args |= BIT (j); } } return combined_args; } /* CombineTypeArguments */ static Bool DetermineRefCountOfAttributeVarsInNode (TypeNode type_node); static Bool DetermineRefCountOfAttributeVarsInTypeConsNode (TypeNode type_node, Symbol type_symb, int nr_of_extra_args, BITVECT extra_prop_args) { TypeArgs type_args; int arg_nr; Bool contains_propating_univars = False; ConsVarList cons_vars; BITVECT uniprop, cons_var_vect, propagating_args = ALLBITSCLEAR; if (type_symb -> symb_kind == definition) { cons_var_vect = DetermineConsVarsOfTypeCons (type_symb -> symb_def, & cons_vars); uniprop = DetermineUniPropOfTypeCons (type_symb -> symb_def); } else { cons_var_vect = ALLBITSCLEAR; cons_vars = NULL; if (type_symb -> symb_kind == fun_type) uniprop = ALLBITSCLEAR; else if (type_symb -> symb_kind == apply_symb) uniprop = BIT (0); else uniprop = ALLBITSSET; } for (type_args = type_node -> type_node_arguments, arg_nr=0; type_args; type_args = type_args -> type_arg_next, arg_nr++) { if (! BITTEST (cons_var_vect, arg_nr)) { if (DetermineRefCountOfAttributeVarsInNode (type_args -> type_arg_node)) { propagating_args |= BIT(arg_nr); if (BITTEST (uniprop, arg_nr)) contains_propating_univars = True; } } } for (type_args = type_node -> type_node_arguments, arg_nr=0; cons_vars; cons_vars = cons_vars -> cvl_next) { for (; type_args != NULL && arg_nr < cons_vars -> cvl_number; arg_nr++, type_args = type_args -> type_arg_next) ; if (type_args != NULL) { TypeNode cons_node = type_args -> type_arg_node; if (cons_node -> type_node_is_var) { if (DetermineRefCountOfAttributeVarsInTypeVar (cons_node) && BITTEST (uniprop, arg_nr)) contains_propating_univars = True; } else { BITVECT comb_args_prop = CombineTypeArguments (cons_vars, type_node -> type_node_arity, propagating_args, nr_of_extra_args, extra_prop_args); if (DetermineRefCountOfAttributeVarsInTypeConsNode (cons_node, cons_node -> type_node_symbol, cons_vars -> cvl_arity, comb_args_prop) && BITTEST (uniprop, arg_nr)) contains_propating_univars = True; } } } if (! contains_propating_univars) { extra_prop_args &= uniprop >> type_node -> type_node_arity; for (arg_nr = 0; arg_nr < nr_of_extra_args; arg_nr ++) { if (BITTEST (extra_prop_args, arg_nr)) { contains_propating_univars = True; break; } } } if (type_node -> type_node_attribute >= FirstUniVarNumber) { UpdateRefCountInfo (type_node -> type_node_attribute - FirstUniVarNumber, contains_propating_univars); return True; } else return contains_propating_univars; } /* DetermineRefCountOfAttributeVarsInTypeConsNode */ static Bool DetermineRefCountOfAttributeVarsInNode (TypeNode type_node) { if (type_node -> type_node_is_var) return DetermineRefCountOfAttributeVarsInTypeVar (type_node); else { Symbol typesymb = type_node -> type_node_symbol; if (typesymb -> symb_kind < Nr_Of_Basic_Types) { if (type_node -> type_node_attribute >= FirstUniVarNumber) { UpdateRefCountInfo (type_node -> type_node_attribute - FirstUniVarNumber, False); return True; } else return False; } else return DetermineRefCountOfAttributeVarsInTypeConsNode (type_node, typesymb, 0, ALLBITSCLEAR); } } /* DetermineRefCountOfAttributeVarsInNode */ static char *TypeConv = "typeconv"; static unsigned RetrieveRefCountInfo (int attr_var, Bool *used_implicitly) { ARC_Info attrinfo = CurrentARC_Info; unsigned newnumber = 0; int i; while (attr_var >= 32) { attr_var -= 32; for (i = 0; i < 32; i++) { if (BITTEST (attrinfo -> arci_multiply_used, i)) newnumber++; } attrinfo = attrinfo -> arci_next; Assume (attrinfo != NULL, TypeConv, "RetrieveRefCountInfo"); } if (BITTEST (attrinfo -> arci_multiply_used, attr_var)) { for (i = 0; i < attr_var; i++) { if (BITTEST (attrinfo -> arci_multiply_used, i)) newnumber++; } *used_implicitly = False; return newnumber + 1; } else { *used_implicitly = BITTEST (attrinfo -> arci_implicitly_attributed, attr_var); return 0; } } /* RetrieveRefCountInfo */ static char *PrintVars = "abcdefghijklmnopqrst"; #define NrOfPrintVars 20 static char *PrintUniVars = "uvwxyz"; #define NrOfPrintUniVars 6 #define cDoPrintAnnot True #define cDontPrintAnnot False static void PrintNode (TypeNode node, Bool brackets, Bool strict_context, Bool print_annot); static unsigned RetrieveRefCountInfo (int attr_var, Bool *used_implicitly); static void PrintAttributeVariable (unsigned attr_nr) { if (attr_nr <= NrOfPrintUniVars) FPrintF (StdListTypes, "%c", PrintUniVars [attr_nr - 1]); else FPrintF (StdListTypes, "u%d", attr_nr - NrOfPrintUniVars); } /* PrintAttributeVariable */ extern Bool DoShowAttributes; #define cDoPrintColon True static Bool PrintAttribute (AttributeKind attr, Bool print_colon) { if (attr == UniqueAttr) { FPutC ('*', StdListTypes); return True; } else if (DoShowAttributes) { Bool used_implicitly; unsigned attr_nr = RetrieveRefCountInfo (attr - FirstUniVarNumber, & used_implicitly); if (attr_nr == 0) { if (! used_implicitly) { FPutC ('.', StdListTypes); return True; } else return False; } else { PrintAttributeVariable (attr_nr); if (print_colon) FPutC (':', StdListTypes); return True; } } else return False; } /* PrintAttribute */ #define cDoPrintAttribute True #define cDontPrintAttribute False #define cInAStrictContext True #define cNotInAStrictContext False #define cPrintBrackets True #define cDontPrintBrackets False static void PrintArgument (TypeArgs arg, Bool brackets, Bool strict_context, Bool print_attribute) { if (arg -> type_arg_node -> type_node_is_var) { if (strict_context) #ifdef STATES_GENERATED # if 1 strict_context = arg -> type_arg_node -> type_node_annotation==StrictAnnot; # else strict_context = !IsLazyState (arg -> type_arg_node -> type_node_state); # endif #else strict_context = arg -> type_arg_node -> type_node_state.state_kind == StrictOnA; #endif if ( strict_context && (DoListAllTypes || DoListStrictTypes) && #ifdef STATES_GENERATED # if 1 arg -> type_arg_node -> type_node_annotation==StrictAnnot) # else !IsLazyState (arg -> type_arg_node -> type_node_state)) # endif #else arg -> type_arg_node -> type_node_state.state_kind == StrictOnA) #endif FPutC ('!', StdListTypes); if (print_attribute && arg -> type_arg_node -> type_node_attribute > NoAttr) PrintAttribute (arg -> type_arg_node -> type_node_attribute, arg -> type_arg_node -> type_node_tv != NULL); if (arg -> type_arg_node -> type_node_tv) { if (arg -> type_arg_node -> type_node_tv -> tv_ident) FPutS (arg -> type_arg_node -> type_node_tv -> tv_ident -> ident_name, StdListTypes); else FPrintF (StdListTypes, "i%ld", arg -> type_arg_node -> type_node_tv); } } else PrintNode (arg -> type_arg_node, brackets, strict_context, cDoPrintAnnot); } /* PrintArgument */ static void PrintArguments (TypeArgs args, char separator, Bool brackets, Bool strict_context, FlatType form_type) { if (args) { int arg_nr; TypeVarList form_type_vars; if (form_type != NULL) { form_type_vars = form_type -> ft_arguments; PrintArgument (args, brackets, strict_context, ! TestMark (form_type_vars -> tvl_elem, tv_mark, TV_EXISTENTIAL_ATTRIBUTE_MASK)); form_type_vars = form_type_vars -> tvl_next; } else { form_type_vars = NULL; PrintArgument (args, brackets, strict_context, cDoPrintAttribute); } for (arg_nr = 1, args = args -> type_arg_next; args; args = args -> type_arg_next, arg_nr++) { FPutC (separator, StdListTypes); if (form_type_vars != NULL) { PrintArgument (args, brackets, strict_context, ! TestMark (form_type_vars -> tvl_elem, tv_mark, TV_EXISTENTIAL_ATTRIBUTE_MASK)); form_type_vars = form_type_vars -> tvl_next; } else PrintArgument (args, brackets, strict_context, cDoPrintAttribute); } } } /* PrintArguments */ #ifdef CLEAN2 static void PrintTypeVarList (TypeVarList type_vars) { for (; type_vars != NULL; type_vars = type_vars -> tvl_next) { /* RWS: Printing the attributes currently works because the attributes for universally quantified type variables can only be none, '*' or '.'. For attribute variables something should probably done with the CurrentARC_Info administration, but I don't understand how this works. */ if (type_vars -> tvl_attribute != NoUniAttr) PrintAttribute (type_vars -> tvl_attribute, cDoPrintColon); FPutS (type_vars -> tvl_elem -> tv_ident -> ident_name, StdListTypes); if (type_vars -> tvl_next != NULL) FPutC (' ', StdListTypes); } } #endif static FlatType RetrieveLhsOfTypeDefinition (SymbDef tdef) { switch (tdef -> sdef_kind) { case TYPE: case RECORDTYPE: return tdef -> sdef_type != NULL ? tdef -> sdef_type -> type_lhs : NULL; case TYPESYN: return tdef -> sdef_syn_type -> syn_lhs; break; case ABSTYPE: return tdef -> sdef_abs_type -> abs_graph; break; default: return NULL; } } /* RetrieveLhsOfTypeDefinition */ static void PrintNode (TypeNode node, Bool brackets, Bool strict_context, Bool print_annot) { if (print_annot && strict_context && (DoListAllTypes || DoListStrictTypes) && #ifdef STATES_GENERATED # if 1 node -> type_node_annotation==StrictAnnot) # else !IsLazyState (node -> type_node_state)) # endif #else node -> type_node_state.state_kind == StrictOnA) #endif FPutC ('!', StdListTypes); if (node -> type_node_attribute > NoAttr) { if (PrintAttribute (node -> type_node_attribute, cDoPrintColon) && (node -> type_node_symbol -> symb_kind == fun_type || node -> type_node_symbol -> symb_kind == apply_symb)) brackets = True; } #ifdef CLEAN2 if (node -> type_for_all_vars != NULL) { FPutS ("(A.", StdListTypes); PrintTypeVarList (node -> type_for_all_vars); FPutC (':', StdListTypes); brackets = False; } #endif switch (node -> type_node_symbol -> symb_kind) { case tuple_type: { int form_arity = node -> type_node_symbol -> symb_arity; if (node -> type_node_arity == form_arity) { FPutC ('(', StdListTypes); PrintArguments (node -> type_node_arguments, ',', cDontPrintBrackets, strict_context, NULL); FPutC (')', StdListTypes); } else { int i; if (brackets && node -> type_node_arguments) FPutC ('(', StdListTypes); FPutC ('(', StdListTypes); for (i=1; i type_node_arguments) { PrintArguments (node -> type_node_arguments, ' ', cPrintBrackets, strict_context, NULL); if (brackets) FPutC (')', StdListTypes); } } break; } case list_type: FPutC ('[', StdListTypes); #if STRICT_LISTS if (node->type_node_symbol->symb_head_strictness==2) FPutC ('!', StdListTypes); else if (node->type_node_symbol->symb_head_strictness==3 || node->type_node_symbol->symb_head_strictness==4) FPutC ('#', StdListTypes); #endif PrintArguments (node -> type_node_arguments, ',', cDontPrintBrackets, cNotInAStrictContext, NULL); #if STRICT_LISTS if (node->type_node_symbol->symb_tail_strictness) FPutC ('!', StdListTypes); #endif FPutC (']', StdListTypes); break; case array_type: FPutS ("{", StdListTypes); PrintArguments (node -> type_node_arguments, ',', cDontPrintBrackets, cInAStrictContext, NULL); FPutS ("}", StdListTypes); break; case strict_array_type: FPutS ("{!", StdListTypes); PrintArguments (node -> type_node_arguments, ',', cDontPrintBrackets, cInAStrictContext, NULL); FPutS ("}", StdListTypes); break; case unboxed_array_type: FPutS ("{#", StdListTypes); PrintArguments (node -> type_node_arguments, ',', cDontPrintBrackets, cInAStrictContext, NULL); FPutS ("}", StdListTypes); break; case fun_type: { TypeNode arg_type_node = node -> type_node_arguments -> type_arg_node; if (brackets) FPutC ('(', StdListTypes); PrintArgument (node -> type_node_arguments, cPrintBrackets, cNotInAStrictContext, cDoPrintAttribute); FPutS (" -> ", StdListTypes); PrintArgument (node -> type_node_arguments -> type_arg_next, cDontPrintBrackets, cNotInAStrictContext, cDoPrintAttribute); if (brackets) FPutC (')', StdListTypes); break; } case apply_symb: if (brackets) FPutC ('(', StdListTypes); PrintArguments (node -> type_node_arguments, ' ', cPrintBrackets, strict_context, NULL); if (brackets) FPutC (')', StdListTypes); break; default: if (brackets && node -> type_node_arguments) FPutC ('(', StdListTypes); PrintSymbol (node -> type_node_symbol, StdListTypes); if (node -> type_node_arguments) { FlatType lhs_type; if (node -> type_node_symbol -> symb_kind == definition) lhs_type = RetrieveLhsOfTypeDefinition (node -> type_node_symbol -> symb_def); else lhs_type = NULL; FPutC (' ', StdListTypes); PrintArguments (node -> type_node_arguments,' ', cPrintBrackets, strict_context, lhs_type); if (brackets) FPutC (')', StdListTypes); } break; } #ifdef CLEAN2 if (node -> type_for_all_vars != NULL) FPutC (')', StdListTypes); #endif } /* PrintNode */ static void PrintAttributeEquations (UniVarEquations attr_equas) { FPutS (", [", StdListTypes); for ( ; ; ) { AttributeKindList next; Bool used_implicitly; unsigned dem_attr_nr = RetrieveRefCountInfo (attr_equas -> uve_demanded - FirstUniVarNumber, & used_implicitly); for (next = attr_equas -> uve_offered ; ; ) { unsigned off_attr_nr = RetrieveRefCountInfo (next -> akl_elem - FirstUniVarNumber, & used_implicitly); PrintAttributeVariable (off_attr_nr); if ((next = next -> akl_next)) FPutC (' ', StdListTypes); else break; } FPutS (" <= ", StdListTypes); PrintAttributeVariable (dem_attr_nr); if ((attr_equas = attr_equas -> uve_next)) FPutS (", ", StdListTypes); else break; } FPutC (']', StdListTypes); } /* PrintAttributeEquations */ #include void PrintTypeClass (SymbDef class_def, File file) { char * class_name = class_def -> sdef_ident -> ident_name; if (*class_name == '.') class_name++; FPutS (class_name, file); } /* PrintTypeClass */ static void PrintTypeContext (TypeContext context) { SymbolList class_symbs = context -> tyco_symbols; TypeVar context_var = context -> tyco_variable; PrintTypeClass (class_symbs -> sl_symbol, StdListTypes); for (class_symbs = class_symbs -> sl_next; class_symbs; class_symbs = class_symbs -> sl_next) { FPutS (" , ", StdListTypes); PrintTypeClass (class_symbs -> sl_symbol, StdListTypes); } FPutC (' ', StdListTypes); if (TestMark (context_var, tv_mark, TV_WITH_INST_RESTR)) FPutC ('.', StdListTypes); FPutS (context_var -> tv_ident -> ident_name, StdListTypes); } /* PrintTypeContext */ void PrintType (SymbDef tdef, TypeAlts type) { TypeNode lhs_root = type -> type_alt_lhs; TypeArgs lhsargs = lhs_root -> type_node_arguments; PrintSymbolOfIdent (tdef -> sdef_ident, tdef -> sdef_line, StdListTypes); FPutS (" :: ", StdListTypes); if (lhsargs) { PrintArguments (lhsargs,' ', cPrintBrackets, cInAStrictContext, NULL); FPutS (" -> ", StdListTypes); } if (type -> type_alt_rhs -> type_node_is_var) { if (type -> type_alt_rhs -> type_node_attribute > NoAttr) PrintAttribute (type -> type_alt_rhs -> type_node_attribute, cDoPrintColon); FPutS (type -> type_alt_rhs -> type_node_tv -> tv_ident -> ident_name, StdListTypes); } else { Bool rhs_brackets = (lhsargs == NULL) && (type -> type_alt_rhs -> type_node_symbol -> symb_kind == fun_type); PrintNode (type -> type_alt_rhs, rhs_brackets, cInAStrictContext, cDontPrintAnnot); } if (type -> type_alt_type_context) { TypeContext next_context; FPutS (" | ", StdListTypes); PrintTypeContext (type -> type_alt_type_context); for (next_context = type -> type_alt_type_context -> tyco_next; next_context; next_context = next_context -> tyco_next) { FPutS (" & ", StdListTypes); PrintTypeContext (next_context); } } if (DoShowAttributes && type -> type_alt_attr_equations) PrintAttributeEquations (type -> type_alt_attr_equations); FPutS (";\n", StdListTypes); } /* PrintType */ void ListTypes (ImpMod imod) { if (DoListAllTypes) { ImpRules irule; for (irule = imod -> im_rules; irule; irule = irule -> rule_next) { SymbDef imp_sdef = irule -> rule_root -> node_symbol -> symb_def; #ifdef CLEAN2 if (strncmp (imp_sdef->sdef_ident->ident_name, "_dictionary", 11) != 0 || imp_sdef->sdef_isused) #endif PrintType (imp_sdef, irule -> rule_type); } } } /* ListTypes */ void InitARC_Info (void) { CurrentARC_Info = CompAllocType (struct attr_ref_count_info); CurrentARC_Info -> arci_next = NULL; } /* InitARC_Info */