Browse code

script engine: different operators for int and str +

- different operators for integer + (RVE_IPLUS_OP) and str plus
(RVE_CONCAT_OP). The generic plus (RVE_PLUS_OP) is still
present, the new operators are only used in internal
optimizations (see below) for now.
- if an expression involving the generic '+' is always of type int
or str, replace the generic '+' with the interger or string
version (makes further optimizations possible).

Andrei Pelinescu-Onciul authored on 18/12/2008 13:46:05
Showing 2 changed files
... ...
@@ -385,10 +385,13 @@ enum rval_type rve_guess_type( struct rval_expr* rve)
385 385
 		case RVE_LTE_OP:
386 386
 		case RVE_EQ_OP:
387 387
 		case RVE_DIFF_OP:
388
+		case RVE_IPLUS_OP:
388 389
 			return RV_INT;
389 390
 		case RVE_PLUS_OP:
390 391
 			/* '+' evaluates to the type of the left operand */
391 392
 			return rve_guess_type(rve->left.rve);
393
+		case RVE_CONCAT_OP:
394
+			return RV_STR;
392 395
 		case RVE_NONE_OP:
393 396
 			break;
394 397
 	}
... ...
@@ -437,6 +440,8 @@ int rve_is_constant(struct rval_expr* rve)
437 440
 		case RVE_EQ_OP:
438 441
 		case RVE_DIFF_OP:
439 442
 		case RVE_PLUS_OP:
443
+		case RVE_IPLUS_OP:
444
+		case RVE_CONCAT_OP:
440 445
 			return rve_is_constant(rve->left.rve) &&
441 446
 					rve_is_constant(rve->right.rve);
442 447
 		case RVE_NONE_OP:
... ...
@@ -473,6 +478,8 @@ static int rve_op_unary(enum rval_expr_op op)
473 478
 		case RVE_EQ_OP:
474 479
 		case RVE_DIFF_OP:
475 480
 		case RVE_PLUS_OP:
481
+		case RVE_IPLUS_OP:
482
+		case RVE_CONCAT_OP:
476 483
 			return 0;
477 484
 		case RVE_NONE_OP:
478 485
 			return -1;
... ...
@@ -532,6 +539,7 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
532 539
 		case RVE_GTE_OP:
533 540
 		case RVE_LT_OP:
534 541
 		case RVE_LTE_OP:
542
+		case RVE_IPLUS_OP:
535 543
 			*type=RV_INT;
536 544
 			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
537 545
 				if (type1==RV_STR){
... ...
@@ -587,6 +595,28 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
587 595
 					return 1;
588 596
 				}
589 597
 			}
598
+		case RVE_CONCAT_OP:
599
+			*type=RV_STR;
600
+			if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
601
+				if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
602
+									exp_t)){
603
+					if ((type2!=type1) && (type1!=RV_NONE) &&
604
+							(type2!=RV_NONE) && 
605
+							!(type1==RV_STR && type2==RV_INT)){
606
+						if (bad_rve) *bad_rve=rve->right.rve;
607
+						if (bad_t) *bad_t=type2;
608
+						if (exp_t) *exp_t=type1;
609
+						return 0;
610
+					}
611
+					if (type1==RV_INT){
612
+						if (bad_rve) *bad_rve=rve->left.rve;
613
+						if (bad_t) *bad_t=type1;
614
+						if (exp_t) *exp_t=RV_STR;
615
+						return 0;
616
+					}
617
+					return 1;
618
+				}
619
+			}
590 620
 		case RVE_NONE_OP:
591 621
 			break;
592 622
 	}
... ...
@@ -936,6 +966,7 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
936 966
 {
937 967
 	switch(op){
938 968
 		case RVE_PLUS_OP:
969
+		case RVE_IPLUS_OP:
939 970
 			*res=v1+v2;
940 971
 			break;
941 972
 		case RVE_MINUS_OP:
... ...
@@ -981,6 +1012,10 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
981 1012
 		case RVE_DIFF_OP:
982 1013
 			*res=v1 != v2;
983 1014
 			break;
1015
+		case RVE_CONCAT_OP:
1016
+			*res=0;
1017
+			/* invalid operand for int */
1018
+			return -1;
984 1019
 		default:
985 1020
 			BUG("rv unsupported intop %d\n", op);
986 1021
 			return -1;
... ...
@@ -1286,6 +1321,7 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1286 1321
 		case RVE_DIV_OP:
1287 1322
 		case RVE_MINUS_OP:
1288 1323
 		case RVE_PLUS_OP:
1324
+		case RVE_IPLUS_OP:
1289 1325
 		case RVE_BOR_OP:
1290 1326
 		case RVE_BAND_OP:
1291 1327
 		case RVE_GT_OP:
... ...
@@ -1376,6 +1412,10 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1376 1412
 				rval_destroy(rv2);
1377 1413
 			break;
1378 1414
 #endif
1415
+		case RVE_CONCAT_OP:
1416
+			*res=0;
1417
+			ret=-1;
1418
+			break;
1379 1419
 		case RVE_NONE_OP:
1380 1420
 		/*default:*/
1381 1421
 			BUG("invalid rval int expression operation %d\n", rve->op);
... ...
@@ -1446,6 +1486,7 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
1446 1486
 		case RVE_LTE_OP:
1447 1487
 		case RVE_EQ_OP:
1448 1488
 		case RVE_DIFF_OP:
1489
+		case RVE_IPLUS_OP:
1449 1490
 			/* operator forces integer type */
1450 1491
 			ret=rval_expr_eval_int(h, msg, res_i, rve);
1451 1492
 			*res_rv=0;
... ...
@@ -1479,6 +1520,10 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
1479 1520
 			}
1480 1521
 			rval_cache_clean(&c1);
1481 1522
 			break;
1523
+		case RVE_CONCAT_OP:
1524
+			*res_rv=rval_expr_eval(h, msg, rve);
1525
+			ret=-(*res_rv==0);
1526
+			break;
1482 1527
 		case RVE_NONE_OP:
1483 1528
 		/*default:*/
1484 1529
 			BUG("invalid rval expression operation %d\n", rve->op);
... ...
@@ -1535,6 +1580,7 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
1535 1580
 		case RVE_LTE_OP:
1536 1581
 		case RVE_EQ_OP:
1537 1582
 		case RVE_DIFF_OP:
1583
+		case RVE_IPLUS_OP:
1538 1584
 			/* operator forces integer type */
1539 1585
 			r=rval_expr_eval_int(h, msg, &i, rve);
1540 1586
 			if (likely(r==0)){
... ...
@@ -1603,6 +1649,19 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
1603 1649
 			}
1604 1650
 			rval_cache_clean(&c1);
1605 1651
 			break;
1652
+		case RVE_CONCAT_OP:
1653
+			rv1=rval_expr_eval(h, msg, rve->left.rve);
1654
+			if (unlikely(rv1==0)){
1655
+				ERR("rval expression evaluation failed\n");
1656
+				goto error;
1657
+			}
1658
+			rv2=rval_expr_eval(h, msg, rve->right.rve);
1659
+			if (unlikely(rv2==0)){
1660
+				ERR("rval expression evaluation failed\n");
1661
+				goto error;
1662
+			}
1663
+			ret=rval_str_add2(h, msg, rv1, 0, rv2, 0);
1664
+			break;
1606 1665
 		case RVE_NONE_OP:
1607 1666
 		/*default:*/
1608 1667
 			BUG("invalid rval expression operation %d\n", rve->op);
... ...
@@ -1767,8 +1826,10 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
1767 1826
 		case RVE_LT_OP:
1768 1827
 		case RVE_LTE_OP:
1769 1828
 		case RVE_PLUS_OP:
1829
+		case RVE_IPLUS_OP:
1770 1830
 		case RVE_EQ_OP:
1771 1831
 		case RVE_DIFF_OP:
1832
+		case RVE_CONCAT_OP:
1772 1833
 			break;
1773 1834
 		default:
1774 1835
 			BUG("unsupported operator %d\n", op);
... ...
@@ -1802,6 +1863,8 @@ static int rve_op_is_assoc(enum rval_expr_op op)
1802 1863
 		case RVE_MINUS_OP:
1803 1864
 			return 0;
1804 1865
 		case RVE_PLUS_OP:
1866
+		case RVE_IPLUS_OP:
1867
+		case RVE_CONCAT_OP:
1805 1868
 		case RVE_MUL_OP:
1806 1869
 		case RVE_BAND_OP:
1807 1870
 		case RVE_BOR_OP:
... ...
@@ -1838,6 +1901,7 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
1838 1901
 			return 0;
1839 1902
 		case RVE_PLUS_OP:
1840 1903
 			return type==RV_INT; /* commutative only for INT*/
1904
+		case RVE_IPLUS_OP:
1841 1905
 		case RVE_MUL_OP:
1842 1906
 		case RVE_BAND_OP:
1843 1907
 		case RVE_BOR_OP:
... ...
@@ -1851,6 +1915,7 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
1851 1915
 		case RVE_LTE_OP:
1852 1916
 		case RVE_EQ_OP:
1853 1917
 		case RVE_DIFF_OP:
1918
+		case RVE_CONCAT_OP:
1854 1919
 			return 0;
1855 1920
 	}
1856 1921
 	return 0;
... ...
@@ -2158,9 +2223,10 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
2158 2223
 				}
2159 2224
 				break;
2160 2225
 			case RVE_PLUS_OP:
2226
+			case RVE_IPLUS_OP:
2161 2227
 				/* we must make sure that this is an int PLUS
2162 2228
 				   (because "foo"+0 is valid => "foo0") */
2163
-				if ((i==0) && (rve_type==RV_INT)){
2229
+				if ((i==0) && ((op==RVE_IPLUS_OP)||(rve_type==RV_INT))){
2164 2230
 					/* $v +  0 -> $v
2165 2231
 					 *  0 + $v -> $v */
2166 2232
 					rve_destroy(ct_rve);
... ...
@@ -2206,14 +2272,32 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
2206 2272
 							op, i);
2207 2273
 			}
2208 2274
 		}
2209
-	}
2210
-	/* no optimization for strings for now
2275
+	}else if (rv->type==RV_STR){
2276
+		switch(op){
2277
+			case RVE_CONCAT_OP:
2278
+				if (rv->v.s.len==0){
2279
+					/* $v . "" -> $v 
2280
+					   "" . $v -> $v */
2281
+					rve_destroy(ct_rve);
2282
+					pos=rve->fpos;
2283
+					*rve=*v_rve; /* replace current expr. with $v */
2284
+					rve->fpos=pos;
2285
+					pkg_free(v_rve);/* rve_destroy(v_rve) would free
2286
+									   everything*/
2287
+					ret=1;
2288
+				}
2289
+				break;
2290
+			default:
2291
+				break;
2292
+		}
2293
+	/* no optimization for generic RVE_PLUS_OP for now, only for RVE_CONCAT_OP
2211 2294
 	   (We could optimize $v + "" or ""+$v, but this ""+$v is a way
2212 2295
 	    to force convert $v to str , it might mess up type checking
2213 2296
 	    (e.g. errors w/o optimization and no errors with) and it brings
2214 2297
 	    a very small benefit anyway (it's unlikely we'll see a lot of
2215 2298
 	    "")
2216 2299
 	*/
2300
+	}
2217 2301
 	if (rv) rval_destroy(rv);
2218 2302
 	return ret;
2219 2303
 error:
... ...
@@ -2232,7 +2316,7 @@ static int rve_optimize(struct rval_expr* rve)
2232 2316
 	enum rval_expr_op op;
2233 2317
 	int flags;
2234 2318
 	struct rval_expr tmp_rve;
2235
-	enum rval_type type;
2319
+	enum rval_type type, l_type;
2236 2320
 	struct rval_expr* bad_rve;
2237 2321
 	enum rval_type bad_type, exp_type;
2238 2322
 	
... ...
@@ -2285,7 +2369,7 @@ static int rve_optimize(struct rval_expr* rve)
2285 2369
 				rv->v.l=-rv->v.l;
2286 2370
 				if (rve_replace_with_ct_rv(rve->right.rve, rv)<0)
2287 2371
 					goto error;
2288
-				rve->op=RVE_PLUS_OP;
2372
+				rve->op=RVE_IPLUS_OP;
2289 2373
 				DBG("FIXUP RVE: optimized $v - a into $v + (%d)\n",
2290 2374
 								(int)rve->right.rve->left.rval.v.l);
2291 2375
 			}
... ...
@@ -2293,6 +2377,22 @@ static int rve_optimize(struct rval_expr* rve)
2293 2377
 			rv=0;
2294 2378
 		}
2295 2379
 		
2380
+		/* e1 PLUS_OP e2 -> change op if we know e1 basic type */
2381
+		if (rve->op==RVE_PLUS_OP){
2382
+			l_type=rve_guess_type(rve->left.rve);
2383
+			if (l_type==RV_INT){
2384
+				rve->op=RVE_IPLUS_OP;
2385
+				DBG("FIXUP RVE (%d,%d-%d,%d): changed + into interger plus\n",
2386
+						rve->fpos.s_line, rve->fpos.s_col,
2387
+						rve->fpos.e_line, rve->fpos.e_col);
2388
+			}else if (l_type==RV_STR){
2389
+				rve->op=RVE_CONCAT_OP;
2390
+				DBG("FIXUP RVE (%d,%d-%d,%d): changed + into string concat\n",
2391
+						rve->fpos.s_line, rve->fpos.s_col,
2392
+						rve->fpos.e_line, rve->fpos.e_col);
2393
+			}
2394
+		}
2395
+		
2296 2396
 		/* $v * 0 => 0; $v * 1 => $v (for *, /, &, |, &&, ||, +, -) */
2297 2397
 		if (rve_opt_01(rve, type)==1){
2298 2398
 			/* success, rve was changed => return now
... ...
@@ -2510,8 +2610,10 @@ int fix_rval_expr(void** p)
2510 2610
 		case RVE_LT_OP:
2511 2611
 		case RVE_LTE_OP:
2512 2612
 		case RVE_PLUS_OP:
2613
+		case RVE_IPLUS_OP:
2513 2614
 		case RVE_EQ_OP:
2514 2615
 		case RVE_DIFF_OP:
2616
+		case RVE_CONCAT_OP:
2515 2617
 			ret=fix_rval_expr((void**)&rve->left.rve);
2516 2618
 			if (ret<0) return ret;
2517 2619
 			ret=fix_rval_expr((void**)&rve->right.rve);
... ...
@@ -59,10 +59,12 @@ enum rval_expr_op{
59 59
 	RVE_GTE_OP,   /*  2 members, returns left >= right */
60 60
 	RVE_LT_OP,    /*  2 members, returns left  < right */
61 61
 	RVE_LTE_OP,   /*  2 members, returns left <= right */
62
+	RVE_IPLUS_OP, /* 2 members, integer +, returns int(a)+int(b) */
62 63
 	/* common int & str */
63
-	RVE_PLUS_OP,  /* 2 members, returns left + right  (int or str)*/
64
+	RVE_PLUS_OP,  /* generic plus (int or str) returns left + right */
64 65
 	RVE_EQ_OP,    /*  2 members, returns left == right  (int)*/
65 66
 	RVE_DIFF_OP,  /*  2 members, returns left != right  (int)*/
67
+	RVE_CONCAT_OP,/* string concatenation, returns left . right */
66 68
 	/* str only */
67 69
 };
68 70