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 242
 	pv_value_t* pv;
243 243
 	enum rval_type tmp;
244 244
 	enum rval_type* ptype;
245
-
245
+	
246 246
 	switch(rv->type){
247 247
 		case RV_INT:
248 248
 		case RV_STR:
... ...
@@ -454,10 +484,21 @@ static int rve_op_unary(enum rval_expr_op op)
454 454
 
455 455
 
456 456
 /** returns 1 if expression is valid (type-wise).
457
+  * @param type - filled with the type of the expression (RV_INT, RV_STR or
458
+  *                RV_NONE if it's dynamic)
459
+  * @param rve  - checked expression
460
+  * @param bad_rve - set on failure to the subexpression for which the 
461
+  *                    type check failed
462
+  * @param bad_type - set on failure to the type of the bad subexpression
463
+  * @param exp_type - set on failure to the expected type for the bad
464
+  *                   subexpression
457 465
   * @return 0 or 1  and sets *type to the resulting type
458 466
   * (RV_INT, RV_STR or RV_NONE if it can be found only at runtime)
459 467
   */
460
-int rve_check_type(enum rval_type* type, struct rval_expr* rve)
468
+int rve_check_type(enum rval_type* type, struct rval_expr* rve,
469
+					struct rval_expr** bad_rve, 
470
+					enum rval_type* bad_t,
471
+					enum rval_type* exp_t)
461 472
 {
462 473
 	enum rval_type type1, type2;
463 474
 	
... ...
@@ -469,9 +510,13 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
469 469
 		case RVE_BOOL_OP:
470 470
 		case RVE_LNOT_OP:
471 471
 			*type=RV_INT;
472
-			if (rve_check_type(&type1, rve->left.rve)){
473
-				if (type1==RV_STR)
472
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
473
+				if (type1==RV_STR){
474
+					if (bad_rve) *bad_rve=rve->left.rve;
475
+					if (bad_t) *bad_t=type1;
476
+					if (exp_t) *exp_t=RV_INT;
474 477
 					return 0;
478
+				}
475 479
 				return 1;
476 480
 			}
477 481
 			return 0;
... ...
@@ -488,12 +533,21 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
488 488
 		case RVE_LT_OP:
489 489
 		case RVE_LTE_OP:
490 490
 			*type=RV_INT;
491
-			if (rve_check_type(&type1, rve->left.rve)){
492
-				if (type1==RV_STR)
491
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
492
+				if (type1==RV_STR){
493
+					if (bad_rve) *bad_rve=rve->left.rve;
494
+					if (bad_t) *bad_t=type1;
495
+					if (exp_t) *exp_t=RV_INT;
493 496
 					return 0;
494
-				if (rve_check_type(&type2, rve->right.rve)){
495
-					if (type2==RV_STR)
497
+				}
498
+				if (rve_check_type(&type2, rve->right.rve, bad_rve,
499
+									bad_t, exp_t)){
500
+					if (type2==RV_STR){
501
+						if (bad_rve) *bad_rve=rve->left.rve;
502
+						if (bad_t) *bad_t=type2;
503
+						if (exp_t) *exp_t=RV_INT;
496 504
 						return 0;
505
+					}
497 506
 					return 1;
498 507
 				}
499 508
 			}
... ...
@@ -501,23 +555,34 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
501 501
 		case RVE_EQ_OP:
502 502
 		case RVE_DIFF_OP:
503 503
 			*type=RV_INT;
504
-			if (rve_check_type(&type1, rve->left.rve)){
505
-				if (rve_check_type(&type2, rve->right.rve)){
504
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
505
+				if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
506
+										exp_t)){
506 507
 					if ((type2!=type1) && (type1!=RV_NONE) &&
507 508
 							(type2!=RV_NONE) && 
508
-							!(type1==RV_STR && type2==RV_INT))
509
+							!(type1==RV_STR && type2==RV_INT)){
510
+						if (bad_rve) *bad_rve=rve->right.rve;
511
+						if (bad_t) *bad_t=type2;
512
+						if (exp_t) *exp_t=type1;
509 513
 						return 0;
514
+					}
510 515
 					return 1;
511 516
 				}
512 517
 			}
513 518
 			return 0;
514 519
 		case RVE_PLUS_OP:
515
-			if (rve_check_type(&type1, rve->left.rve)){
516
-				if (rve_check_type(&type2, rve->right.rve)){
520
+			*type=RV_NONE;
521
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
522
+				if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
523
+									exp_t)){
517 524
 					if ((type2!=type1) && (type1!=RV_NONE) &&
518 525
 							(type2!=RV_NONE) && 
519
-							!(type1==RV_STR && type2==RV_INT))
526
+							!(type1==RV_STR && type2==RV_INT)){
527
+						if (bad_rve) *bad_rve=rve->right.rve;
528
+						if (bad_t) *bad_t=type2;
529
+						if (exp_t) *exp_t=type1;
520 530
 						return 0;
531
+					}
521 532
 					*type=type1;
522 533
 					return 1;
523 534
 				}
... ...
@@ -1879,6 +1944,8 @@ static int rve_optimize(struct rval_expr* rve)
1879 1879
 	int flags;
1880 1880
 	struct rval_expr tmp_rve;
1881 1881
 	enum rval_type type;
1882
+	struct rval_expr* bad_rve;
1883
+	enum rval_type bad_type, exp_type;
1882 1884
 	
1883 1885
 	ret=0;
1884 1886
 	flags=0;
... ...
@@ -1912,8 +1979,10 @@ static int rve_optimize(struct rval_expr* rve)
1912 1912
 			return rve_optimize(rve->left.rve);
1913 1913
 		rve_optimize(rve->left.rve);
1914 1914
 		rve_optimize(rve->right.rve);
1915
-		if (!rve_check_type(&type, rve)){
1916
-			ERR("optimization failure, type mismatch in expression\n");
1915
+		if (!rve_check_type(&type, rve, &bad_rve, &bad_type, &exp_type)){
1916
+			ERR("optimization failure, type mismatch in expression, "
1917
+					"type %s, but expected %s\n",
1918
+					rval_type_name(bad_type), rval_type_name(exp_type));
1917 1919
 			return 0;
1918 1920
 		}
1919 1921
 		/* 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
   */