| 9352 | |
| 9353 | |
| 9354 | ResultType Line::FinalizeExpression(ArgStruct &aArg) |
| 9355 | { |
| 9356 | auto stack = (ExprTokenType **)_alloca(aArg.max_stack * sizeof(ExprTokenType **)); |
| 9357 | int stack_count = 0; |
| 9358 | // stack_count checks: Since missing operands are caught at an earlier stage, it doesn't |
| 9359 | // seem possible to produce any situation where the stack is unbalanced, but due to the |
| 9360 | // overall complexity it seems best to assume that it could happen. Having these checks |
| 9361 | // here might help catch future (or present) bugs. |
| 9362 | |
| 9363 | for (auto this_postfix = aArg.postfix; this_postfix->symbol != SYM_INVALID; ++this_postfix) |
| 9364 | { |
| 9365 | auto postfix_symbol = this_postfix->symbol; |
| 9366 | ASSERT((UINT)postfix_symbol < SYM_COUNT); |
| 9367 | if (IS_OPERAND(postfix_symbol)) |
| 9368 | { |
| 9369 | if (postfix_symbol == SYM_DYNAMIC) |
| 9370 | { |
| 9371 | if (stack_count < 1) |
| 9372 | return LineError(ERR_EXPR_SYNTAX); |
| 9373 | --stack_count; |
| 9374 | } |
| 9375 | stack[stack_count++] = this_postfix; |
| 9376 | } |
| 9377 | else if (IS_POSTFIX_OPERATOR(postfix_symbol) || IS_PREFIX_OPERATOR(postfix_symbol)) |
| 9378 | { |
| 9379 | if (stack_count < 1) |
| 9380 | return LineError(ERR_EXPR_SYNTAX); |
| 9381 | stack[stack_count - 1] = this_postfix; |
| 9382 | } |
| 9383 | else if (SYM_USES_CIRCUIT_TOKEN(postfix_symbol)) |
| 9384 | { |
| 9385 | if (stack_count < 1) |
| 9386 | return LineError(ERR_EXPR_SYNTAX); |
| 9387 | // Pop the result of the left branch of this short-circuit operator, then just allow the right branch |
| 9388 | // to be evaluated and its value/token used as the result. A consequence of this simple approach is |
| 9389 | // that when a short-circuit expression is passed as a parameter, only the right branch... |
| 9390 | // 1) is permitted to be something like &A_Index, being passed to a built-in output var param. |
| 9391 | // 2) is resolved to a function address in something like DllCall(a || "B") or DllCall(a?"B":"C"). |
| 9392 | // If this is changed, be sure that both branches are "finalized"; i.e. don't just skip over the right |
| 9393 | // branch, since it might contain invalid function calls. This seems difficult to do in one pass since |
| 9394 | // the end of the right branch isn't marked in any way, but it can be done by having a recursive call |
| 9395 | // finalize from [this_postfix] to [this_postfix->circuit_token], then having this layer skip it. |
| 9396 | --stack_count; |
| 9397 | } |
| 9398 | else if (postfix_symbol == SYM_COMMA) |
| 9399 | { |
| 9400 | if (stack_count < 1) |
| 9401 | return LineError(ERR_EXPR_SYNTAX); |
| 9402 | --stack_count; |
| 9403 | } |
| 9404 | else if (postfix_symbol != SYM_FUNC) |
| 9405 | { |
| 9406 | if (stack_count < 2) |
| 9407 | return LineError(ERR_EXPR_SYNTAX); |
| 9408 | --stack_count; // Pop RHS |
| 9409 | stack[stack_count - 1] = this_postfix; // Replace LHS |
| 9410 | } |
| 9411 | else // SYM_FUNC |
no test coverage detected