/* $Id: constant.c,v 1.24 2005/02/08 14:23:26 sbeyer Exp $ $Log: constant.c,v $ Revision 1.24 2005/02/08 14:23:26 sbeyer * removed unnecessary default which caused strange compile error on gcc 3.4 Revision 1.23 2001/08/21 11:08:06 dirkl - removed error in simplification of negative constants Revision 1.22 2001/06/12 20:13:38 sbeyer * simplified cond case simplification Revision 1.21 2001/06/12 18:52:55 sbeyer * fixed cond case simplification bug Revision 1.20 2001/06/11 12:38:47 sbeyer * fixed nat recursive function support Revision 1.19 2001/06/11 11:36:53 sbeyer * added nat function support Revision 1.18 2001/04/20 13:45:32 dirkl - added support for records in conds Revision 1.17 2001/01/25 15:26:44 sbeyer added 'vereinfache_cond_case_list' Revision 1.16 2001/01/25 10:44:18 sbeyer finally wrote real 'safe' functions for allocating and deallocation nodes and strings; allocated node is now initialized with zeroes Revision 1.15 2001/01/24 16:52:48 sbeyer added full support for function bit selection (i.e. expr(i) = expr^i) Revision 1.14 2001/01/23 18:26:02 sbeyer support for several 'constant' functions, numerous bugfixes Revision 1.13 2001/01/18 16:06:04 sbeyer now a little less verbose :-) Revision 1.12 2001/01/16 17:27:28 sbeyer better allocation/deallocation treatment Revision 1.11 2001/01/15 15:58:00 sbeyer removed backend from project; moved 2 functions from backend to constant Revision 1.10 2001/01/15 15:11:09 sbeyer cosmetic changes (like const qualifier) Revision 1.9 2001/01/11 11:47:28 sbeyer renamed subknoten to sub in struct knoten Revision 1.8 2001/01/09 16:27:31 sbeyer *** empty log message *** */ #include "constant.h" #include #include // legt einen Teil-Parsebaum für einen Booleschen Wert an struct knoten* bool_knoten(struct knoten* knot,int wert) { struct knoten *temp2; int i; for (i=0;isubanz;i++) knoten_speicherfreigeben(knot->sub[i]); knot->typ=expr; knot->subtyp=159; // expr -> name knot->subanz=1; temp2=alloc_knoten(); temp2->typ=name_token; temp2->subtyp=347; // name -> idop temp2->subanz=1; temp2->wert_str=NULL; temp2->source_line=knot->source_line; temp2->source_file=knot->source_file; knot->sub[0]=temp2; temp2=alloc_knoten(); temp2->typ=idop; temp2->subtyp=332; // idop -> opsym temp2->subanz=1; temp2->wert_str=NULL; temp2->source_line=knot->source_line; temp2->source_file=knot->source_file; knot->sub[0]->sub[0]=temp2; temp2=alloc_knoten(); temp2->typ=opsym; temp2->subanz=0; temp2->wert_str=NULL; temp2->source_line=knot->source_line; temp2->source_file=knot->source_file; if (wert==0) { temp2->subtyp=378; // opsym -> false } else { temp2->subtyp=377; // opsym -> true } knot->sub[0]->sub[0]->sub[0]=temp2; return knot; } // legt einen Teil-Parsebaum für einen Integer Wert an struct knoten* int_knoten(struct knoten* knot,int wert,double dwert) { struct knoten *temp2; int i; for (i=0;isubanz;i++) knoten_speicherfreigeben(knot->sub[i]); knot->typ=expr; knot->subtyp=157; // expr -> NUMBER_token knot->subanz=1; temp2=alloc_knoten(); temp2->typ=NUMBER_token; temp2->subtyp=no_subtyp; temp2->wert_int=wert; temp2->wert_double=dwert; temp2->wert_str=NULL; temp2->subanz=0; temp2->source_line=knot->source_line; temp2->source_file=knot->source_file; knot->sub[0]=temp2; return knot; } // berechnet a hoch b int potenz(int a,int b) { if (b==0) return 1; if (b<0) return 1/potenz(a,-b); return(a*potenz(a,b-1)); } // gibt 1 zurueck, falls knot eine Konstante ist, ansonsten 0 int is_constant(const struct knoten *const knot) { if (knot->subtyp==157) // expr -> NUMBER { return 1; } else { return 0; } } // gibt den Wert einer Konstanten zurück int get_constant_value(const struct knoten *const knot) { return (knot->sub[0]->wert_int); } double get_double_value(const struct knoten *const knot) { return (knot->sub[0]->wert_double); } // gibt den Wert einer Bool-Konstanten zurueck int get_bool_constant_value(const struct knoten *const knot) { if (knot->sub[0]->sub[0]->sub[0]->subtyp==377) { return 1; } return 0; } // gibt 1 zurueck, falls knot von der Form expr->....->TRUE bzw. expr->....->FALSE IST; ansonsten 0 int is_bool_constant(const struct knoten *const knot) { if (knot->subtyp==159) if (knot->sub[0]->subtyp==347) if (knot->sub[0]->sub[0]->subtyp==332) if ((knot->sub[0]->sub[0]->sub[0]->subtyp==377) || (knot->sub[0]->sub[0]->sub[0]->subtyp==378)) return 1; return 0; } void get_bool_expr(const struct knoten *const knot, int *value) { if (knot->sub[0]->sub[0]->sub[0]->subtyp==377) // if erster_operand==true *value=1; else *value=0; } void get_bool_args(const struct knoten *const knot, int *op1, int *op2) { get_bool_expr(knot->sub[0],op1); get_bool_expr(knot->sub[1],op2); } void get_const_expr(const struct knoten *const knot, int *value, double *dvalue) { *value =knot->sub[0]->wert_int; *dvalue=knot->sub[0]->wert_double; } void get_const_args(const struct knoten *const knot, int *op1, int *op2, double *dop1, double *dop2) { get_const_expr(knot->sub[0],op1,dop1); get_const_expr(knot->sub[1],op2,dop2); } // berechnet einfache expressions, dir nur aus Bool-Konstanten bestehen; z.B. : TRUE or FALSE wir zu TRUE ausgewertet struct knoten * berechne_bool_expression(struct knoten *knot) { int ergebnis; int op1,op2; struct knoten *rueckgabe_knoten=knot; // falls auswerten nicht moeglich ==> standardmaessig den alten Knoten zurueckliefern switch(knot->subtyp) { case 174 : // expr OR expr get_bool_args(knot,&op1,&op2); if (op1 || op2) ergebnis=1; else ergebnis=0; if (parameter_verbose) printf ("%s or %s \t==> %s\n",boolstring[op1],boolstring[op2],boolstring[ergebnis]); // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; case 176 : // expr AND expr case 178 : { get_bool_args(knot,&op1,&op2); if (op1 && op2) ergebnis=1; else ergebnis=0; if (parameter_verbose) { printf ("%s and %s \t==> %s\n",boolstring[op1],boolstring[op2],boolstring[ergebnis]); } // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; } case 179 : // expr XOR expr { get_bool_args(knot,&op1,&op2); if ((op1==0 && op2==1) || (op1==1 && op2==0)) ergebnis=1; else ergebnis=0; if (parameter_verbose) { printf ("%s xor %s \t==> %s\n",boolstring[op1],boolstring[op2],boolstring[ergebnis]); } // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; } case 171 : // expr implies expr case 172 : { get_bool_args(knot,&op1,&op2); if ((op1==0) || (op1==1 && op2==1)) ergebnis=1; else ergebnis=0; if (parameter_verbose) { printf ("%s implies %s \t==> %s\n",boolstring[op1],boolstring[op2],boolstring[ergebnis]); } // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; } case 173 : // expr when expr { get_bool_args(knot,&op1,&op2); if ((op2==0) || (op2==1 && op1==1)) ergebnis=1; else ergebnis=0; if (parameter_verbose) { printf ("%s when %s \t==> %s\n",boolstring[op1],boolstring[op2],boolstring[ergebnis]); } // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; } case 169 : // expr <=> expr case 170 : { get_bool_args(knot,&op1,&op2); if (op1==op2) ergebnis=1; else ergebnis=0; if (parameter_verbose) { printf ("%s <=> %s \t==> %s\n",boolstring[op1],boolstring[op2],boolstring[ergebnis]); } // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; } case 210 : // not expr { get_bool_expr(knot,&op1); if (op1==1) ergebnis=0; else ergebnis=1; if (parameter_verbose) { printf ("not %s \t==> %s\n",boolstring[op1],boolstring[ergebnis]); } // das Ergebnis im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; } default : if (parameter_verbose) printf ("Unbekannte Expression vom Subtyp %d konnte nicht ausgewertet werden.\n",knot->subtyp); } return rueckgabe_knoten; } // berechnet einfache expressions, die nur aus Konstanten bestehen; z.B. : 5*4 wird zu 20 ausgewertet struct knoten * berechne_const_expression(struct knoten *knot) { int op1,op2,ergebnis; double dop1,dop2,dergebnis; struct knoten *rueckgabe_knoten=knot; // falls auswerten nicht moeglich ==> standardmaessig den alten Knoten zurueckliefern switch(knot->subtyp) { // Numeric Expressions case 182 : // expr ^ expr get_const_args(knot,&op1,&op2,&dop1,&dop2); ergebnis=potenz(op1,op2); if (parameter_verbose) printf ("%d^%d \t==> %d\n",op1,op2,ergebnis); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=int_knoten(knot,ergebnis,ergebnis); rueckgabe_knoten=knot; break; case 183 : // expr + expr get_const_args(knot,&op1,&op2,&dop1,&dop2); ergebnis = op1+ op2; dergebnis=dop1+dop2; if (parameter_verbose) printf ("%d+%d \t==> %d\n",op1,op2,ergebnis); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=int_knoten(knot,ergebnis,dergebnis); rueckgabe_knoten=knot; break; case 184 : // expr - expr get_const_args(knot,&op1,&op2,&dop1,&dop2); ergebnis = op1- op2; dergebnis=dop1-dop2; if (parameter_verbose) printf ("%d-%d \t==> %d\n",op1,op2,ergebnis); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=int_knoten(knot,ergebnis,dergebnis); rueckgabe_knoten=knot; break; case 185 : // expr * expr get_const_args(knot,&op1,&op2,&dop1,&dop2); ergebnis = op1* op2; dergebnis=dop1*dop2; if (parameter_verbose) printf ("%d*%d \t==> %d\n",op1,op2,ergebnis); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=int_knoten(knot,ergebnis,dergebnis); rueckgabe_knoten=knot; break; case 186 : // expr / expr get_const_args(knot,&op1,&op2,&dop1,&dop2); ergebnis = op1/ op2; dergebnis=dop1/dop2; if (parameter_verbose) printf ("%d/%d \t==> %d\n",op1,op2,ergebnis); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=int_knoten(knot,ergebnis,dergebnis); rueckgabe_knoten=knot; break; case 214 : // -expr get_const_expr(knot->sub[0],&op1,&dop1); ergebnis =- op1; dergebnis=-dop1; if (parameter_verbose) printf ("-%d \t==> %d\n",op1,ergebnis); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=int_knoten(knot,ergebnis,dergebnis); rueckgabe_knoten=knot; break; case 199 : // expr < expr get_const_args(knot,&op1,&op2,&dop1,&dop2); if (dop1 %s\n",dop1,dop2,boolstring[ergebnis]); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; case 200 : // expr <= expr get_const_args(knot,&op1,&op2,&dop1,&dop2); if (dop1<=dop2) ergebnis=1; else ergebnis=0; if (parameter_verbose) printf ("%f<=%f \t==> %s\n",dop1,dop2,boolstring[ergebnis]); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; case 201 : // expr > expr get_const_args(knot,&op1,&op2,&dop1,&dop2); if (dop1>dop2) ergebnis=1; else ergebnis=0; if (parameter_verbose) printf ("%f>%f \t==> %s\n",dop1,dop2,boolstring[ergebnis]); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; case 202 : // expr >= expr get_const_args(knot,&op1,&op2,&dop1,&dop2); if (dop1>=dop2) ergebnis=1; else ergebnis=0; if (parameter_verbose) printf ("%f>=%f \t==> %s\n",dop1,dop2,boolstring[ergebnis]); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; case 196 : // expr = expr get_const_args(knot,&op1,&op2,&dop1,&dop2); if (dop1==dop2) ergebnis=1; else ergebnis=0; if (parameter_verbose) printf ("%f==%f \t==> %s\n",dop1,dop2,boolstring[ergebnis]); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; case 197 : // expr /= expr get_const_args(knot,&op1,&op2,&dop1,&dop2); if (dop1!=dop2) ergebnis=1; else ergebnis=0; if (parameter_verbose) printf ("%f/=%f \t==> %s\n",dop1,dop2,boolstring[ergebnis]); // das ergebnis eines bin-infix Operators im Parse-Tree als Konstante ablegen knot=bool_knoten(knot,ergebnis); rueckgabe_knoten=knot; break; default : if (parameter_verbose) printf ("Unbekannte Expression vom Subtyp %d konnte nicht ausgewertet werden.\n",knot->subtyp); } return rueckgabe_knoten; } // fasst Konstante Expressions in einem ganzen Teilbaum zusammen struct knoten *vereinfache_teilbaum(struct knoten *knot) { int i; struct knoten *rueckgabe=knot; switch (knot->typ) { case expr : rueckgabe=vereinfache_expression(knot); break; default : for (i=0;isubanz;i++) { knot->sub[i]=vereinfache_teilbaum(knot->sub[i]); } } return rueckgabe; } void all_expr_constant(const struct knoten *const knot, int *bool_constant, int *constant) { int konstanten_zaehler,boolkonstanten_zaehler,i; konstanten_zaehler=0; boolkonstanten_zaehler=0; for (i=0;isubanz;i++) if (knot->sub[i]->typ==expr) { if (is_constant(knot->sub[i])) konstanten_zaehler++; if (is_bool_constant(knot->sub[i])) boolkonstanten_zaehler++; } else { all_expr_constant(knot->sub[i],bool_constant,constant); if (*constant==1) konstanten_zaehler++; if (*bool_constant==1) boolkonstanten_zaehler++; } if (konstanten_zaehler==knot->subanz) *constant=1; else *constant=0; if (boolkonstanten_zaehler==knot->subanz) *bool_constant=1; else *bool_constant=0; } struct knoten *vereinfache_cond_case_list(struct knoten *knot) { int i; // the first sub-node is always cond_case! if (is_bool_constant(knot->sub[0]->sub[0])) { i=get_bool_constant_value(knot->sub[0]->sub[0]); switch (knot->subtyp) { case 233 : // cond_case_list -> cond_case if (i==0) knot_error(printf("all conditions in cond-case-list evaluate to false\n"),knot); return knot->sub[0]->sub[1]; case 235 : // cond_case_list -> cond_case ELSE MINUSGROESSER expr return i==1? knot->sub[0]->sub[1] : knot->sub[1]; case 234 : // cond_case_list -> cond_case, cond_case_list return i==1? knot->sub[0]->sub[1] : vereinfache_cond_case_list(knot->sub[1]); default : knot_error(printf("Aufruf von vereinfache_cond_case_list mit unzulaessigem Subtyp\n"),knot) } } return knot; // nothing to simplify } // fasst Konstanten in Expressions zusammen struct knoten *vereinfache_expression(struct knoten *knot) { int i, j, constant, bool_constant; double x; struct knoten *rueckgabe_knoten=knot; struct knoten *tempknoten; struct knoten *tempknoten2; struct knoten *tempknoten3; struct knoten *tempknoten4; // FIRST, traverse the subtree to simplify ALL expressions!!! for (i=0;isubanz;i++) // bei if (zunächst!!!) nur die Bedingung vereinfachen if (!((knot->subtyp==218 || knot->subtyp==219) && i)) if (knot->sub[i]->typ==expr) knot->sub[i]=vereinfache_expression(knot->sub[i]); else knot->sub[i]=vereinfache_teilbaum(knot->sub[i]); switch(knot->subtyp) { // subtypen, die als sub nur expr enthalten case 168 : case 169 : case 170 : case 171 : case 172 : case 173 : case 174 : case 175 : case 176 : case 177 : case 178 : case 179 : case 180 : case 181 : case 182 : case 183 : case 184 : case 185 : case 186 : case 187 : case 188 : case 189 : case 190 : case 191 : case 192 : case 193 : case 194 : case 195 : case 196 : case 197 : case 198 : case 199 : case 200 : case 201 : case 202 : case 203 : case 204 : case 205 : case 206 : case 207 : case 208 : case 209 : case 210 : case 211 : case 212 : case 213 : case 214 : all_expr_constant(knot,&bool_constant,&constant); // falls alle Sub Konstanten sind, kann die Expression evtl. zu einer Konstanten ausgewertet werden if (constant==1) { rueckgabe_knoten=berechne_const_expression(knot); if (parameter_verbose) printf ("Knoten vom Typ %s Subtyp %d (als Sub nur Konstanten) ausgewertet.\n",token_string[knot->typ],knot->subtyp); } // falls alle Sub Bool-Konstanten sind, die Expr. evtl. zu einer Bool-Konstanten auswerten if (bool_constant==1) { rueckgabe_knoten=berechne_bool_expression(knot); if (parameter_verbose) printf ("Knoten vom Typ %s Subtyp %d (als Sub nur Bool-Konstanten) ausgewertet.\n",token_string[knot->typ],knot->subtyp); } break; // Klammerausdruck case 164 : if ((knot->sub[0]->subtyp==246) && ((is_constant(knot->sub[0]->sub[0]) || (is_bool_constant(knot->sub[0]->sub[0]))))) // Klammer um Konstanten werden weggelassen { rueckgabe_knoten=copysyntaxbaum(knot->sub[0]->sub[0]); knoten_speicherfreigeben(knot); if (parameter_verbose) printf("Klammer um Konstante wegoptimiert.\n"); } break; case 218 : // if { // falls die Bedingung eine Bool-Konstante ist, wird das IF durch die passende Konsequenz ersetzt rueckgabe_knoten=knot; if (is_bool_constant(knot->sub[0])) { if (get_bool_constant_value(knot->sub[0])==1) { // das if... durch die 1. Konsequenz ersetzen if (parameter_verbose) { printf ("IF aufgeloest zu 1. Konsequenz\n"); } tempknoten=copysyntaxbaum(knot->sub[1]); knoten_speicherfreigeben(knot); rueckgabe_knoten=vereinfache_expression(tempknoten); } else { // das if... durch die 2. Konsequenz ersetzen if (parameter_verbose) { printf ("IF aufgeloest zu 2. Konsequenz\n"); } tempknoten=copysyntaxbaum(knot->sub[2]); knoten_speicherfreigeben(knot); tempknoten=vereinfache_expression(tempknoten); rueckgabe_knoten=tempknoten; } } else for (i=1;isubanz;i++) if (knot->sub[i]->typ==expr) knot->sub[i]=vereinfache_expression(knot->sub[i]); else knot->sub[i]=vereinfache_teilbaum(knot->sub[i]); break; } case 219 : // if ... elseif { // falls die Bedingung eine Bool-Konstante ist, wird das IF durch die passende Konsequenz ersetzt if (is_bool_constant(knot->sub[0])) { if (get_bool_constant_value(knot->sub[0])==1) { // das if... durch die 1. Konsequenz ersetzen tempknoten=copysyntaxbaum(knot->sub[1]); knoten_speicherfreigeben(knot); rueckgabe_knoten=vereinfache_expression(tempknoten); } else { // den elsif-Teil in ein neues IF umwandeln und dann dieses vereinfachen tempknoten=copysyntaxbaum(knot->sub[2]->sub[0]); // die Bedingung vom elsif-Teil tempknoten2=copysyntaxbaum(knot->sub[2]->sub[1]); // die Konsequenz vom elsif-Teil tempknoten3=copysyntaxbaum(knot->sub[3]); // der else-Teil if (knot->sub[2]->subtyp==242) // elseif_plus => ELSIF expr THEN expr { tempknoten4=NULL; } else { tempknoten4=copysyntaxbaum(knot->sub[2]->sub[2]); // der elsif Teil vom elsif Teil } knoten_speicherfreigeben(knot->sub[0]); knoten_speicherfreigeben(knot->sub[1]); knoten_speicherfreigeben(knot->sub[2]); knoten_speicherfreigeben(knot->sub[3]); // diese Knoten zu neuem IF zusammensetzen knot->wert_str=NULL; knot->sub[0]=tempknoten; knot->sub[1]=tempknoten2; if (tempknoten4) { knot->subtyp=219; // if mit elsif knot->subanz=4; knot->sub[2]=tempknoten4; knot->sub[3]=tempknoten3; } else { knot->subtyp=218; // if ohne elsif knot->subanz=3; knot->sub[2]=tempknoten3; } rueckgabe_knoten=vereinfache_expression(knot); } } else for (i=1;isubanz;i++) if (knot->sub[i]->typ==expr) knot->sub[i]=vereinfache_expression(knot->sub[i]); else knot->sub[i]=vereinfache_teilbaum(knot->sub[i]); break; } case 231 : // COND cond_case_list ENDCOND tempknoten4=vereinfache_cond_case_list(knot->sub[0]); if (tempknoten4!=knot->sub[0]) // real simplification? { // replace knot by rueckgabe_knoten rueckgabe_knoten=copysyntaxbaum(tempknoten4); knoten_speicherfreigeben(knot); knot=vereinfache_teilbaum(rueckgabe_knoten); } rueckgabe_knoten=knot; break; case 159 : // expr -> name if (knot->sub[0]->subtyp==347 && // name -> idop knot->sub[0]->sub[0]->subtyp==331)// idop -> ID { i=compute_nat_function(knot,knot->sub[0]->sub[0]->sub[0]->wert_str,&j); if (j==1) rueckgabe_knoten=int_knoten(knot,i,i); else rueckgabe_knoten=knot; } break; case 167 : // expr -> expr funarg // test expr_leerlist for constant expressions all_expr_constant(knot->sub[1]->sub[0],&bool_constant,&constant); // recognized functions with constant arguments: // odd? // even? // floor // ceiling // mod // div // exp2 if (constant==1 && // all parameters const? knot->sub[0]->subtyp==159 && // expr -> name knot->sub[0]->sub[0]->subtyp==347 && // name -> idop knot->sub[0]->sub[0]->sub[0]->subtyp==331)// idop -> ID { // in the case constant==1, it is already clear that // funarg -> exprleerlist -> exprlist if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"odd?")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=246) // exprlist -> expr knot_error(printf("function odd? must have exactly one arguemnt!\n"),knot); // odd?(x) = x%2 i=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); if (parameter_verbose) printf("odd?(%i) => %i",i,i%2); i%=2; knot=bool_knoten(knot,i); } else if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"even?")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=246) // exprlist -> expr knot_error(printf("function even? must have exactly one arguemnt!\n"),knot); // even?(x) = 1-x%2 i=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); if (parameter_verbose) printf("even?(%i) => %i",i,1-i%2); i=1-i%2; knot=bool_knoten(knot,i); } else if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"floor")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=246) // exprlist -> expr knot_error(printf("function floor must have exactly one arguemnt!\n"),knot); x=get_double_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); i=(int)(floor(x)); if (parameter_verbose) printf("floor(%f) => %i",x,i); knot=int_knoten(knot,i,i); } else if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"ceiling")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=246) // exprlist -> expr knot_error(printf("function ceiling must have exactly one arguemnt!\n"),knot); x=get_double_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); i=(int)(ceil(x)); if (parameter_verbose) printf("ceiling(%f) => %i",x,i); knot=int_knoten(knot,i,i); } else if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"exp2")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=246) // exprlist -> expr knot_error(printf("function exp2 must have exactly one arguemnt!\n"),knot); i=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); if (parameter_verbose) printf("exp2(%i) => %i",i,potenz(2,i)); i=potenz(2,i); knot=int_knoten(knot,i,i); } else if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"mod")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=247) // exprlist -> expr,exprlist knot_error(printf("function mod must have exactly two arguemnts!\n"),knot); if (knot->sub[1]->sub[0]->sub[0]->sub[1]->subtyp!=246) // exprlist -> expr knot_error(printf("function mod must have exactly two arguemnts!\n"),knot); i=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); j=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[1]->sub[0]); if (parameter_verbose) printf("mod(%i,%i) => %i",i,j,i%j); i%=j; knot=int_knoten(knot,i,i); } else if (!strcmp(knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,"div")) { if (knot->sub[1]->sub[0]->sub[0]->subtyp!=247) // exprlist -> expr,exprlist knot_error(printf("function div must have exactly two arguemnts!\n"),knot); if (knot->sub[1]->sub[0]->sub[0]->sub[1]->subtyp!=246) // exprlist -> expr knot_error(printf("function div must have exactly two arguemnts!\n"),knot); i=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[0]); j=get_constant_value(knot->sub[1]->sub[0]->sub[0]->sub[1]->sub[0]); if (parameter_verbose) printf("div(%i,%i) => %i",i,j,i/j); i/=j; knot=int_knoten(knot,i,i); } else { i=compute_nat_function(knot,knot->sub[0]->sub[0]->sub[0]->sub[0]->wert_str,&j); if (j==1) knot=int_knoten(knot,i,i); } rueckgabe_knoten=knot; } break; // default : } return rueckgabe_knoten; } // Berechnet den Wert einer Expression, falls dieser sich berechnen laesst und gibt ansonsten eine Fehlermeldung // aus und -1 zurueck int expression_ausrechnen(struct knoten *expr_knoten) { vereinfache_expression(expr_knoten); if (is_constant(expr_knoten)) { return get_constant_value(expr_knoten); } else { if (parameter_verbose) { printf("Expression konnte nicht ausgerechnet werden.\n"); } return -1; } }