Browse code

script engine: rve_check_type() extended

- extended rve_check_type() to return also the subexpression for
which the check failed, its type and the expected type.

Andrei Pelinescu-Onciul authored on 15/12/2008 20:22:09
Showing 2 changed files
... ...
@@ -191,6 +191,36 @@ struct rvalue* rval_new_str(str* s, int extra_size)
191 191
 
192 192
 
193 193
 
194
+/** get string name for a type.
195
+  *
196
+  * @return - null terminated name of the type
197
+  */
198
+char* rval_type_name(enum rval_type type)
199
+{
200
+	switch(type){
201
+		case RV_NONE:
202
+			return "none";
203
+		case RV_INT:
204
+			return "int";
205
+		case RV_STR:
206
+			return "str";
207
+		case RV_BEXPR:
208
+			return "bexpr_t";
209
+		case RV_ACTION_ST:
210
+			return "action_t";
211
+		case RV_PVAR:
212
+			return "pvar";
213
+		case RV_AVP:
214
+			return "avp";
215
+			break;
216
+		case RV_SEL:
217
+			return "select";
218
+	}
219
+	return "error_unkown_type";
220
+}
221
+
222
+
223
+
194 224
 /** create a new pk_malloc'ed rvalue from a rval_val union.
195 225
   *
196 226
   * @param s - pointer to str, must be non-null
... ...
@@ -242,7 +272,7 @@ inline static enum rval_type rval_get_btype(struct run_act_ctx* h,
242 272
 	pv_value_t* pv;
243 273
 	enum rval_type tmp;
244 274
 	enum rval_type* ptype;
245
-
275
+	
246 276
 	switch(rv->type){
247 277
 		case RV_INT:
248 278
 		case RV_STR:
... ...
@@ -454,10 +484,21 @@ static int rve_op_unary(enum rval_expr_op op)
454 484
 
455 485
 
456 486
 /** returns 1 if expression is valid (type-wise).
487
+  * @param type - filled with the type of the expression (RV_INT, RV_STR or
488
+  *                RV_NONE if it's dynamic)
489
+  * @param rve  - checked expression
490
+  * @param bad_rve - set on failure to the subexpression for which the 
491
+  *                    type check failed
492
+  * @param bad_type - set on failure to the type of the bad subexpression
493
+  * @param exp_type - set on failure to the expected type for the bad
494
+  *                   subexpression
457 495
   * @return 0 or 1  and sets *type to the resulting type
458 496
   * (RV_INT, RV_STR or RV_NONE if it can be found only at runtime)
459 497
   */
460
-int rve_check_type(enum rval_type* type, struct rval_expr* rve)
498
+int rve_check_type(enum rval_type* type, struct rval_expr* rve,
499
+					struct rval_expr** bad_rve, 
500
+					enum rval_type* bad_t,
501
+					enum rval_type* exp_t)
461 502
 {
462 503
 	enum rval_type type1, type2;
463 504
 	
... ...
@@ -469,9 +510,13 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
469 510
 		case RVE_BOOL_OP:
470 511
 		case RVE_LNOT_OP:
471 512
 			*type=RV_INT;
472
-			if (rve_check_type(&type1, rve->left.rve)){
473
-				if (type1==RV_STR)
513
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
514
+				if (type1==RV_STR){
515
+					if (bad_rve) *bad_rve=rve->left.rve;
516
+					if (bad_t) *bad_t=type1;
517
+					if (exp_t) *exp_t=RV_INT;
474 518
 					return 0;
519
+				}
475 520
 				return 1;
476 521
 			}
477 522
 			return 0;
... ...
@@ -488,12 +533,21 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
488 533
 		case RVE_LT_OP:
489 534
 		case RVE_LTE_OP:
490 535
 			*type=RV_INT;
491
-			if (rve_check_type(&type1, rve->left.rve)){
492
-				if (type1==RV_STR)
536
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
537
+				if (type1==RV_STR){
538
+					if (bad_rve) *bad_rve=rve->left.rve;
539
+					if (bad_t) *bad_t=type1;
540
+					if (exp_t) *exp_t=RV_INT;
493 541
 					return 0;
494
-				if (rve_check_type(&type2, rve->right.rve)){
495
-					if (type2==RV_STR)
542
+				}
543
+				if (rve_check_type(&type2, rve->right.rve, bad_rve,
544
+									bad_t, exp_t)){
545
+					if (type2==RV_STR){
546
+						if (bad_rve) *bad_rve=rve->left.rve;
547
+						if (bad_t) *bad_t=type2;
548
+						if (exp_t) *exp_t=RV_INT;
496 549
 						return 0;
550
+					}
497 551
 					return 1;
498 552
 				}
499 553
 			}
... ...
@@ -501,23 +555,34 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
501 555
 		case RVE_EQ_OP:
502 556
 		case RVE_DIFF_OP:
503 557
 			*type=RV_INT;
504
-			if (rve_check_type(&type1, rve->left.rve)){
505
-				if (rve_check_type(&type2, rve->right.rve)){
558
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
559
+				if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
560
+										exp_t)){
506 561
 					if ((type2!=type1) && (type1!=RV_NONE) &&
507 562
 							(type2!=RV_NONE) && 
508
-							!(type1==RV_STR && type2==RV_INT))
563
+							!(type1==RV_STR && type2==RV_INT)){
564
+						if (bad_rve) *bad_rve=rve->right.rve;
565
+						if (bad_t) *bad_t=type2;
566
+						if (exp_t) *exp_t=type1;
509 567
 						return 0;
568
+					}
510 569
 					return 1;
511 570
 				}
512 571
 			}
513 572
 			return 0;
514 573
 		case RVE_PLUS_OP:
515
-			if (rve_check_type(&type1, rve->left.rve)){
516
-				if (rve_check_type(&type2, rve->right.rve)){
574
+			*type=RV_NONE;
575
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
576
+				if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
577
+									exp_t)){
517 578
 					if ((type2!=type1) && (type1!=RV_NONE) &&
518 579
 							(type2!=RV_NONE) && 
519
-							!(type1==RV_STR && type2==RV_INT))
580
+							!(type1==RV_STR && type2==RV_INT)){
581
+						if (bad_rve) *bad_rve=rve->right.rve;
582
+						if (bad_t) *bad_t=type2;
583
+						if (exp_t) *exp_t=type1;
520 584
 						return 0;
585
+					}
521 586
 					*type=type1;
522 587
 					return 1;
523 588
 				}
... ...
@@ -1879,6 +1944,8 @@ static int rve_optimize(struct rval_expr* rve)
1879 1944
 	int flags;
1880 1945
 	struct rval_expr tmp_rve;
1881 1946
 	enum rval_type type;
1947
+	struct rval_expr* bad_rve;
1948
+	enum rval_type bad_type, exp_type;
1882 1949
 	
1883 1950
 	ret=0;
1884 1951
 	flags=0;
... ...
@@ -1912,8 +1979,10 @@ static int rve_optimize(struct rval_expr* rve)
1912 1979
 			return rve_optimize(rve->left.rve);
1913 1980
 		rve_optimize(rve->left.rve);
1914 1981
 		rve_optimize(rve->right.rve);
1915
-		if (!rve_check_type(&type, rve)){
1916
-			ERR("optimization failure, type mismatch in expression\n");
1982
+		if (!rve_check_type(&type, rve, &bad_rve, &bad_type, &exp_type)){
1983
+			ERR("optimization failure, type mismatch in expression, "
1984
+					"type %s, but expected %s\n",
1985
+					rval_type_name(bad_type), rval_type_name(exp_type));
1917 1986
 			return 0;
1918 1987
 		}
1919 1988
 		/* TODO: $v - a => $v + (-a) */
... ...
@@ -185,7 +185,11 @@ enum rval_type rve_guess_type(struct rval_expr* rve);
185 185
 /** returns true if expression is constant. */
186 186
 int rve_is_constant(struct rval_expr* rve);
187 187
 /** returns 1 if expression is valid (type-wise).*/
188
-int rve_check_type(enum rval_type* type, struct rval_expr* rve);
188
+int rve_check_type(enum rval_type* type, struct rval_expr* rve,
189
+					struct rval_expr** bad_rve, enum rval_type* bad_type,
190
+					enum rval_type* exp_type);
191
+/** returns a string name for type (debugging).*/
192
+char* rval_type_name(enum rval_type type);
189 193
 
190 194
 /** create a RVE_RVAL_OP rval_expr, containing a single rval of the given type
191 195
   */