| 7476 | |
| 7477 | |
| 7478 | Line *Script::PreparseCommands(Line *aStartingLine) |
| 7479 | // Preparse any commands which might rely on blocks having been fully preparsed, |
| 7480 | // such as any command which has a jump target (label). |
| 7481 | // Also perform some late-stage optimizations and validation. |
| 7482 | { |
| 7483 | for (Line *line = aStartingLine; line; line = line->mNextLine) |
| 7484 | { |
| 7485 | LPTSTR line_raw_arg1 = LINE_RAW_ARG1; // Resolve only once to help reduce code size. |
| 7486 | LPTSTR line_raw_arg2 = LINE_RAW_ARG2; // |
| 7487 | |
| 7488 | switch (line->mActionType) |
| 7489 | { |
| 7490 | case ACT_BLOCK_BEGIN: |
| 7491 | if (line->mAttribute) // This is the opening brace of a function definition. |
| 7492 | g->CurrentFunc = (UserFunc *)line->mAttribute; // Must be set only for the above condition because functions can of course contain types of blocks other than the function's own block. |
| 7493 | break; |
| 7494 | case ACT_BLOCK_END: |
| 7495 | if (line->mAttribute) // This is the closing brace of a function definition. |
| 7496 | { |
| 7497 | auto &func = *(UserFunc *)line->mAttribute; |
| 7498 | |
| 7499 | g->CurrentFunc = func.mOuterFunc; |
| 7500 | |
| 7501 | Line *block_begin = line->mParentLine; |
| 7502 | Line *parent = block_begin->mParentLine; |
| 7503 | |
| 7504 | if (func.mIsFuncExpression // => |
| 7505 | && block_begin->mParentLine |
| 7506 | && block_begin->mParentLine->mActionType != ACT_BLOCK_BEGIN) |
| 7507 | { |
| 7508 | if (line->mNextLine->mActionType == ACT_BLOCK_BEGIN) // It could only be a fat arrow block-begin under these conditions. |
| 7509 | // There's another =>function after this one (defined within the same |
| 7510 | // expression), so just continue until the last =>function is found. |
| 7511 | continue; |
| 7512 | // This fat arrow function's parent line is a statement with a single-line |
| 7513 | // action, but that action is currently separated from its parent by one or |
| 7514 | // more fat arrow functions. It won't work that way because If/Else/Loop/etc. |
| 7515 | // all skip an initial ACT_BLOCK_BEGIN (to avoid an extra ExecUntil call), |
| 7516 | // which would result in executing the function's body instead of skipping it. |
| 7517 | Line *body = line->mNextLine; |
| 7518 | #ifdef KEEP_FAT_ARROW_FUNCTIONS_IN_LINE_LIST // Currently unused. |
| 7519 | block_begin = parent->mNextLine; // In case there are multiple fat arrow functions on one line. |
| 7520 | Line *after_body = parent->mRelatedLine; |
| 7521 | Line *body_end = after_body->mPrevLine; // In case body is multiple lines (such as a nested IF or LOOP). |
| 7522 | // Swap the statement body and fat arrow functions around to make it work: |
| 7523 | parent ->mNextLine = body , body ->mPrevLine = parent; |
| 7524 | body_end ->mNextLine = block_begin, block_begin->mPrevLine = body_end; |
| 7525 | line ->mNextLine = after_body , after_body ->mPrevLine = line; |
| 7526 | #else |
| 7527 | // Remove the fat arrow functions to allow the correct body to execute. |
| 7528 | // This relies on there being no need for the fat arrow functions to |
| 7529 | // remain in the Line list after this point (so for instance, there's |
| 7530 | // no possibility of setting a breakpoint in one of these functions). |
| 7531 | parent->mNextLine = body, body->mPrevLine = parent; |
| 7532 | #endif |
| 7533 | } |
| 7534 | else if (parent && parent->mActionType != ACT_BLOCK_BEGIN) |
| 7535 | { |
nothing calls this directly
no test coverage detected