Diff
Not logged in

Differences From Artifact [407bfc4d6c]:

To Artifact [f95fb08561]:


476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
476
477
478
479
480
481
482















483
484
485
486
487
488
489







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* a-m */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* n-z */
	BRACED		/* { */,	0		/* | or || */,
	INVALID		/* } */,	BIT_NOT		/* ~ */,
	INVALID		/* DEL */
};

/*
 * The JumpList struct is used to create a stack of data needed for the
 * TclEmitForwardJump() and TclFixupForwardJump() calls that are performed
 * when compiling the short-circuiting operators QUESTION/COLON, AND, and OR.
 * Keeping a stack permits the CompileExprTree() routine to be non-recursive.
 */

typedef struct JumpList {
    JumpFixup jump;		/* Pass this argument to matching calls of
				 * TclEmitForwardJump() and 
				 * TclFixupForwardJump(). */
} JumpList;

TclBrodnikArray(JumpList);

/*
 * Declarations for local functions to this file:
 */

static void		CompileExprTree(Tcl_Interp *interp, OpNode *nodes,
			    int index, Tcl_Obj *const **litObjvPtr,
			    Tcl_Obj *const *funcObjv, Tcl_Token *tokenPtr,
2236
2237
2238
2239
2240
2241
2242


2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258


2259
2260
2261
2262
2263
2264
2265
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243


2244
2245
2246
2247
2248
2249
2250
2251
2252







+
+














-
-
+
+







 *	Adds instructions to envPtr to evaluate the expression at runtime.
 *	Consumes subtree of nodes rooted at index. Advances the pointer
 *	*litObjvPtr.
 *
 *----------------------------------------------------------------------
 */

TclBrodnikArray(JumpFixup);

static void
CompileExprTree(
    Tcl_Interp *interp,
    OpNode *nodes,
    int index,
    Tcl_Obj *const **litObjvPtr,
    Tcl_Obj *const *funcObjv,
    Tcl_Token *tokenPtr,
    CompileEnv *envPtr,
    int optimize)
{
    OpNode *nodePtr = nodes + index;
    OpNode *rootPtr = nodePtr;
    int numWords = 0;
    JumpList *jumpPtr = NULL;
    BA_JumpList *stack = NULL;
    JumpFixup *jumpPtr = NULL;
    BA_JumpFixup *stack = NULL;
    int convert = 1;

    while (1) {
	int next;

	if (nodePtr->mark == MARK_LEFT) {
	    next = nodePtr->left;
2295
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305


2306
2307
2308
2309


2310
2311
2312
2313

2314
2315
2316
2317
2318
2319
2320

2321
2322

2323
2324

2325
2326
2327
2328
2329
2330
2331
2282
2283
2284
2285
2286
2287
2288

2289
2290


2291
2292
2293
2294


2295
2296

2297
2298

2299
2300
2301
2302
2303
2304
2305

2306
2307

2308
2309

2310
2311
2312
2313
2314
2315
2316
2317







-
+

-
-
+
+


-
-
+
+
-


-
+






-
+

-
+

-
+








		nodePtr->left = numWords;
		numWords = 2;	/* Command plus one argument */
		break;
	    }
	    case QUESTION:
		if (stack == NULL) {
		    stack = BA_JumpList_Create();
		    stack = BA_JumpFixup_Create();
		}
		BA_JumpList_Append(stack, &jumpPtr);
		TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpPtr->jump);
		BA_JumpFixup_Append(stack, &jumpPtr);
		TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, jumpPtr);
		break;
	    case COLON:
		BA_JumpList_Append(stack, &jumpPtr);
		TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
		BA_JumpFixup_Append(stack, &jumpPtr);
		TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, jumpPtr);
			&jumpPtr->jump);
		TclAdjustStackDepth(-1, envPtr);
		if (convert) {
		    jumpPtr->jump.jumpType = TCL_TRUE_JUMP;
		    jumpPtr->jumpType = TCL_TRUE_JUMP;
		}
		convert = 1;
		break;
	    case AND:
	    case OR:
		if (stack == NULL) {
		    stack = BA_JumpList_Create();
		    stack = BA_JumpFixup_Create();
		}
		BA_JumpList_Append(stack, &jumpPtr);
		BA_JumpFixup_Append(stack, &jumpPtr);
		TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND)
			?  TCL_FALSE_JUMP : TCL_TRUE_JUMP, &jumpPtr->jump);
			?  TCL_FALSE_JUMP : TCL_TRUE_JUMP, jumpPtr);
		break;
	    }
	} else {
	    int pc1, pc2, target;

	    switch (nodePtr->lexeme) {
	    case START:
2361
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371


2372
2373
2374
2375


2376
2377

2378
2379
2380
2381
2382



2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398

2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422
2423
2347
2348
2349
2350
2351
2352
2353

2354
2355


2356
2357
2358
2359


2360
2361
2362

2363
2364
2365



2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409







-
+

-
-
+
+


-
-
+
+

-
+


-
-
-
+
+
+



-
+











-
+

















-
+







		/*
		 * Each comma implies another function argument.
		 */

		numWords++;
		break;
	    case COLON:
		BA_JumpList_Detach(stack, &jumpPtr);
		BA_JumpFixup_Detach(stack, &jumpPtr);
		CLANG_ASSERT(jumpPtr);
		if (jumpPtr->jump.jumpType == TCL_TRUE_JUMP) {
		    jumpPtr->jump.jumpType = TCL_UNCONDITIONAL_JUMP;
		if (jumpPtr->jumpType == TCL_TRUE_JUMP) {
		    jumpPtr->jumpType = TCL_UNCONDITIONAL_JUMP;
		    convert = 1;
		}
		target = jumpPtr->jump.codeOffset + 2;
		if (TclFixupForwardJump(envPtr, &jumpPtr->jump,
		target = jumpPtr->codeOffset + 2;
		if (TclFixupForwardJump(envPtr, jumpPtr,
			(envPtr->codeNext - envPtr->codeStart)
			- jumpPtr->jump.codeOffset, 127)) {
			- jumpPtr->codeOffset, 127)) {
		    target += 3;
		}
		BA_JumpList_Detach(stack, &jumpPtr);
		TclFixupForwardJump(envPtr, &jumpPtr->jump,
			target - jumpPtr->jump.codeOffset, 127);
		BA_JumpFixup_Detach(stack, &jumpPtr);
		TclFixupForwardJump(envPtr, jumpPtr,
			target - jumpPtr->codeOffset, 127);
		break;
	    case AND:
	    case OR:
		BA_JumpList_Detach(stack, &jumpPtr);
		BA_JumpFixup_Detach(stack, &jumpPtr);
		CLANG_ASSERT(jumpPtr);
		pc1 = CurrentOffset(envPtr);
		TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1
			: INST_JUMP_TRUE1, 0, envPtr);
		TclEmitPush(TclRegisterNewLiteral(envPtr,
			(nodePtr->lexeme == AND) ? "1" : "0", 1), envPtr);
		pc2 = CurrentOffset(envPtr);
		TclEmitInstInt1(INST_JUMP1, 0, envPtr);
		TclAdjustStackDepth(-1, envPtr);
		TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc1,
			envPtr->codeStart + pc1 + 1);
		if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
		if (TclFixupForwardJumpToHere(envPtr, jumpPtr, 127)) {
		    pc2 += 3;
		}
		TclEmitPush(TclRegisterNewLiteral(envPtr,
			(nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr);
		TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2,
			envPtr->codeStart + pc2 + 1);
		convert = 0;
		break;
	    default:
		TclEmitOpcode(instruction[nodePtr->lexeme], envPtr);
		convert = 0;
		break;
	    }
	    if (nodePtr == rootPtr) {
		/* We're done */

		if (stack) {
		    BA_JumpList_Destroy(stack);
		    BA_JumpFixup_Destroy(stack);
		}
		return;
	    }
	    nodePtr = nodes + nodePtr->p.parent;
	    continue;
	}