C:/Users/Dennis/src/lang/russell.orig/src/pass4/infer_args.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include "parm.h"
00003 
00004 #include "stree/ststructs.mh"
00005 
00006 #include "sigs.h"
00007 
00008 # define SIZE_SIZE 8
00009 # define DUMMY -2
00010 # define is_dummy(id) ((id) -> id_str_table_index == DUMMY)
00011 
00012 extern FILE * unparse_file;
00013 
00014 extern int next_pre;
00015 
00016 extern int yynerrs;
00017 
00018 boolean replace_arg();
00019 NODE * mknode();
00020 
00021 extern unsigned indx_subscr;
00022 
00023 extern NODE * var_Void;
00024 
00025 extern NODE * diff_p, * diff_q; /* set by comp_st to point to difference in   */
00026                                 /* trees being compared.  See pass3/comp_st.c */
00027 
00028 /*
00029  *  Return initial_args, with additional arguments appended to make it
00030  * the same length as params.  It is assumed that initial_args can
00031  * be extended to match params.  If this is false, either NIL or some
00032  * garbage argument list (of the same length as params) is returned.
00033  *  The missing arguments are filled in by either unifying corresponding
00034  * arguments and parameters (provided they have non-type signatures)
00035  * or by building an identifier node pointing to void_decl
00036  * for a var Void argument.  If oper is an identifier named ".",
00037  * if it has 3 parameters with val signature, and if there are 2 arguments
00038  * specified, both of which are strings of length < MAXINTLEN, then the third
00039  * argument is inferred to be the length of the second string.
00040  *  It is assumed that signatures for all expressions on the initial
00041  * argument list are known.  It is guaranteed that the same is true
00042  * for the final argument list.
00043  *  It is assumed that the argument list is initially no longer,
00044  * and presumably shorter than the parameter list.
00045  */
00046 
00047 NODE *
00048 infer_args(initial_args, params, void_decl, oper)
00049 NODE * initial_args;
00050 NODE * params;
00051 NODE * void_decl;
00052 NODE * oper;
00053 {
00054     int n_params = length(params);
00055     int n_args = length(initial_args);  /* Number of known arguments */
00056     NODE * new_args;
00057     NODE * Void_id;
00058     int i;
00059     NODE * s_params;  /* parameters after substitution */
00060     boolean failed = FALSE;
00061     boolean is_decimal_point; /* third argument should be length of 2nd one */
00062 
00063 #   ifdef DEBUG
00064       if (nargs() != 4) {
00065         dbgmsg("infer_args: wrong number of arguments\n");
00066       }
00067 #   endif
00068     if (n_args == n_params) return(initial_args);
00069     new_args = lock(copylist(initial_args));
00070     /* determine whether the length of the second arg should be inserted */
00071       is_decimal_point = n_params >= 3 && n_args == 2 &&
00072                          oper -> kind == OPRID &&
00073                          oper -> id_str_table_index == indx_subscr;
00074       if (is_decimal_point) {
00075         int i = 0;
00076         extern boolean Gflag;
00077         extern NODE * val_Integer;
00078 
00079         maplist(s, new_args, {
00080           if (s -> kind != UQSTR) {
00081             is_decimal_point = FALSE;
00082           } else if (!Gflag && strlen(s -> str_string) > MAXINTLEN
00083                      || Gflag && strlen(s -> str_string) > GMAXINTLEN) {
00084             if (comp_st(s -> signature,
00085                         val_Integer, NIL, NIL) == 0) {
00086                 fprintf(stderr, "Warning: possible floating pt const too long\n");
00087             }
00088           }
00089         });
00090         maplist (s, params, {
00091           i++;
00092           if (i <= 3 && s -> par_signature -> kind != VALSIGNATURE) {
00093             is_decimal_point = FALSE;
00094           }
00095         });
00096       }
00097     if (is_decimal_point) {
00098       /* add third argument */
00099         char * new_str_string = (char *) malloc(SIZE_SIZE);
00100         NODE * new_str;
00101         sprintf(new_str_string, "%d",
00102                 strlen(last(new_args) -> str_string));
00103         new_str = mknode(UQSTR, new_str_string);
00104         new_str -> vlineno = oper -> vlineno;
00105         new_str -> str_use_list = first(new_args) -> str_use_list;
00106         if (findsig(new_str,FALSE) != SUCCESS) {
00107           errmsg0(oper, "Can`t find signature for length arg of \".\" ");
00108           new_str -> signature = ERR_SIG;
00109           new_str -> sig_done = SIG_DONE;
00110           return(NIL);
00111         }
00112         addright(new_args, new_str);
00113         n_args++;
00114     }
00115     /* new_args := new_args with parameter identifiers     */
00116     /* inserted for missing arguments.                     */
00117       i = 1;
00118       maplist(s, params, {
00119         if (i > n_args) {
00120           /* Add dummy node */
00121             NODE * dummy_id;
00122             dummy_id = mknode(LETTERID, DUMMY);
00123             dummy_id -> id_last_definition = s;
00124             dummy_id -> id_def_found = TRUE;
00125             dummy_id -> signature = NIL;
00126             addright(new_args, dummy_id);
00127         }
00128         i++;
00129       });
00130     /* add var Void arguments */
00131       if (void_decl != NIL) {
00132         Void_id = lock(mknode(LETTERID, 0));
00133 
00134 #       ifdef DEBUG
00135           if (void_decl -> kind != PARAMETER) {
00136             dbgmsg("infer_args: funny Void variable declaration: 0x%X, %s\n",
00137                    void_decl, kindname(void_decl -> kind));
00138             abort();
00139           }
00140 #       endif
00141         Void_id -> id_last_definition = void_decl;
00142         Void_id -> id_def_found = TRUE;
00143         Void_id -> vlineno = oper -> vlineno;
00144         initfld(&(Void_id -> signature), var_Void);
00145         Void_id -> sig_done = SIG_DONE;
00146         maplist(s, params, {
00147             if (comp_st(s -> par_signature, var_Void, NIL, NIL) == 0) {
00148                 boolean success = replace_arg(new_args, s, Void_id);
00149                 if (success /* arg was missing */) {
00150                     n_args++;
00151                 }
00152             }
00153         });
00154         vfree(unlock(Void_id));
00155       }
00156     /* add arguments derivable by unification of non-type sigs */
00157       while (!failed && n_args < n_params) {
00158         s_params = subst(params, params, new_args);
00159         begin_map2lists(s, s_params, r, new_args) {
00160             if ((r -> kind == LETTERID || r -> kind == OPRID) && is_dummy(r)) {
00161               /* Should have found missing arguments by now */
00162               failed = TRUE;
00163               break; /* out of map2lists */
00164             }
00165             /* real argument */
00166             if (s -> par_signature -> kind != TYPESIGNATURE
00167                 && r -> signature != ERR_SIG) {
00168               NODE * par_to_unify = s -> par_signature;
00169               NODE * arg_to_unify = r -> signature;
00170             
00171               /* Adjust for possible coercions */
00172                 if (par_to_unify -> kind == VALSIGNATURE) {
00173                     if (arg_to_unify -> kind == VARSIGNATURE) {
00174                         arg_to_unify = arg_to_unify -> var_denotation;
00175                         par_to_unify = par_to_unify -> val_denotation;
00176                     } else if (arg_to_unify -> kind == FUNCSIGNATURE
00177                                && is_empty(arg_to_unify -> fsig_param_list)) {
00178                         arg_to_unify = arg_to_unify -> fsig_result_sig;
00179                     }
00180                 }
00181 
00182               /* try to unify argument and parameter signatures */
00183                 if (comp_st(par_to_unify,
00184                             arg_to_unify, NIL, NIL) != 0) {
00185                     NODE * sav_diff_p = diff_p;
00186                     NODE * sav_diff_q = diff_q;
00187 
00188                     if(sav_diff_p != NIL && is_dummy(sav_diff_p) &&
00189                        findsig(sav_diff_q, FALSE) == SUCCESS &&
00190                        replace_arg(new_args, sav_diff_p -> id_last_definition,
00191                                    unshare(sav_diff_q))) {
00192                         /* differed because of missing argument */
00193                         n_args++;
00194                         break;
00195                     } else {
00196                         failed = TRUE;
00197                     }
00198                 }
00199             }
00200         } end_map2lists;
00201       }
00202     unlock(new_args);
00203     if (n_args != n_params) {
00204         vfree(new_args);
00205         return(NIL);
00206     } else {
00207         return(new_args);
00208     }
00209 }
00210 
00211 /*
00212  *  Replace the dummy node in list args which is declared by the node old
00213  * with the expression tree new.  Returns TRUE if such a node was found,
00214  * FALSE otherwise.
00215  */
00216 boolean replace_arg(args, old, new)
00217 NODE * args, * old, * new;
00218 {
00219     int i = 1;  /* index of the element old */
00220     int j;
00221     boolean found_it = FALSE;
00222     
00223     mapinslist(s, args, {
00224         if (s != NIL && 
00225             s -> kind == LETTERID && is_dummy(s) &&
00226             is_declared_by(s, old)) {
00227                 found_it = TRUE;
00228                 DELETE;
00229                 break;
00230         }
00231         i++;
00232     });
00233     if (!found_it) return(FALSE);
00234 
00235     /* Insert new node before position i.  This is a separate loop */
00236     /* only because INSERT followed by DELETE is not guaranteed to */
00237     /* work.                                                       */
00238         j = 1;
00239         mapinslist(s, args, {
00240             if (j == i) {
00241                 INSERT(new);
00242             }
00243             j++;
00244         });
00245     return(TRUE);
00246 }

Generated on Fri Jan 25 10:39:47 2008 for russell by  doxygen 1.5.4