void execSwitchStatement (void) { getCodeToken(); char* branchTableLocation = getCodeAddressMarker(); getCodeToken(); TypePtr switchExpressionTypePtr = execExpression(); long switchExpressionValue; if ((switchExpressionTypePtr == IntegerTypePtr) || (switchExpressionTypePtr->form == FRM_ENUM)) switchExpressionValue = tos->integer; else switchExpressionValue = tos->byte; pop(); //--------------------------------------------------------- // Now, search the branch table for the expression value... codeSegmentPtr = branchTableLocation; getCodeToken(); long caseLabelCount = getCodeInteger(); bool done = false; char* caseBranchLocation = NULL; while (!done && caseLabelCount--) { long caseLabelValue = getCodeInteger(); caseBranchLocation = getCodeAddress(); done = (caseLabelValue == switchExpressionValue); } //----------------------------------------------- // If found, go to the aprropriate branch code... if (caseLabelCount >= 0) { codeSegmentPtr = caseBranchLocation; getCodeToken(); if (codeToken != TKN_END_CASE) do { execStatement(); if (ExitWithReturn) return; } while (codeToken != TKN_END_CASE); //---------------------------------- // Grab the end case and semi-colon... getCodeToken(); getCodeToken(); codeSegmentPtr = getCodeAddressMarker(); getCodeToken(); } else { //----------------------------------------------------------------- // Since the branch table is located at the end of the case blocks, // the code directly after the switch statement follows our // current code location, already. Just grab the endswitch // and semi-colon... getCodeToken(); getCodeToken(); } }
void execIfStatement(void) { getCodeToken(); PSTR falseLocation = getCodeAddressMarker(); //------------------------------- // Eval the boolean expression. Note that, unlike C/C++, the expression // must be true(1) or false(0). In C/C++, an expression is true if it's // non-zero. Not the case in ABL using this current implementation. Do we // want to change this? getCodeToken(); execExpression(); bool test = (tos->integer == 1); pop(); if(test) { //--------------------------- // execute the TRUE branch... getCodeToken(); if((codeToken != TKN_END_IF) && (codeToken != TKN_ELSE)) do { execStatement(); if(ExitWithReturn) return; } while((codeToken != TKN_END_IF) && (codeToken != TKN_ELSE)); if(codeToken == TKN_ELSE) { getCodeToken(); codeSegmentPtr = getCodeAddressMarker(); getCodeToken(); } } else { //---------------------------- // Execute the FALSE branch... codeSegmentPtr = falseLocation; getCodeToken(); if(codeToken == TKN_ELSE) { getCodeToken(); getCodeAddressMarker(); getCodeToken(); if(codeToken != TKN_END_IF) do { execStatement(); if(ExitWithReturn) return; } while(codeToken != TKN_END_IF); } } getCodeToken(); }
void execWhileStatement (void) { getCodeToken(); char* loopEndLocation = getCodeAddressMarker(); char* testLocation = codeSegmentPtr; bool loopDone = false; long iterations = 0; do { //------------------------------- // Eval the boolean expression... getCodeToken(); execExpression(); if (tos->integer == 0) { codeSegmentPtr = loopEndLocation; loopDone = true; } //------------------------- // Get the boolean value... pop(); //---------------------------------- // If TRUE, execute the statement... if (!loopDone) { getCodeToken(); if (codeToken != TKN_END_WHILE) do { execStatement(); if (ExitWithReturn) return; } while (codeToken != TKN_END_WHILE); codeSegmentPtr = testLocation; //--------------------------- // Check for infinite loop... iterations++; if (iterations == MaxLoopIterations) runtimeError(ABL_ERR_RUNTIME_INFINITE_LOOP); } } while (!loopDone); getCodeToken(); }
void execForStatement(void) { getCodeToken(); //--------------------------------------- // Grab address of the end of the loop... PSTR loopEndLocation = getCodeAddressMarker(); //-------------------------------------------------------- // Get the address of the control variable's stack item... getCodeToken(); SymTableNodePtr controlIdPtr = getCodeSymTableNodePtr(); TypePtr controlTypePtr = execVariable(controlIdPtr, USE_TARGET); StackItemPtr targetPtr = (StackItemPtr)tos->address; //------------------------------------ // Control variable address... pop(); //------------------------------- // Eval the initial expression... getCodeToken(); execExpression(); int32_t initialValue; if(controlTypePtr == IntegerTypePtr) initialValue = tos->integer; else initialValue = tos->byte; //--------------------- // The initial value... pop(); int32_t deltaValue; if(codeToken == TKN_TO) deltaValue = 1; else deltaValue = -1; //---------------------------------- // Now, eval the final expression... getCodeToken(); execExpression(); int32_t finalValue; if(controlTypePtr == IntegerTypePtr) finalValue = tos->integer; else finalValue = tos->byte; //------------------- // The final value... pop(); //---------------------------- // Address of start of loop... PSTR loopStartLocation = codeSegmentPtr; int32_t controlValue = initialValue; //----------------------------- // Now, execute the FOR loop... int32_t iterations = 0; if(deltaValue == 1) while(controlValue <= finalValue) { if(controlTypePtr == IntegerTypePtr) targetPtr->integer = controlValue; else targetPtr->byte = (uint8_t)controlValue; getCodeToken(); if(codeToken != TKN_END_FOR) do { execStatement(); if(ExitWithReturn) return; } while(codeToken != TKN_END_FOR); //--------------------------- // Check for infinite loop... if(++iterations == MaxLoopIterations) runtimeError(ABL_ERR_RUNTIME_INFINITE_LOOP); controlValue++; codeSegmentPtr = loopStartLocation; } else while(controlValue >= finalValue) { if(controlTypePtr == IntegerTypePtr) targetPtr->integer = controlValue; else targetPtr->byte = (uint8_t)controlValue; getCodeToken(); if(codeToken != TKN_END_FOR) do { execStatement(); if(ExitWithReturn) return; } while(codeToken != TKN_END_FOR); //--------------------------- // Check for infinite loop... if(++iterations == MaxLoopIterations) runtimeError(ABL_ERR_RUNTIME_INFINITE_LOOP); controlValue--; codeSegmentPtr = loopStartLocation; } codeSegmentPtr = loopEndLocation; getCodeToken(); }