Sunday, June 20, 2010

Translation – INPUT command

Without going the entire process in how the translation was arrived at, here is the general form of the translated INPUT statement (optional items in square brackets, repeating items in braces):
[<expr>] InputGet {<variable> InputType}... Input
The InputGet code will output an optional prompt string (evaluated by the preceding string expression and pushed to the evaluation stack) and the “? ” if selected, and then will get the input. The InputType codes will parse the input for a appropriate data type. Any errors cause a loop back to the InputGet code (where the prompt is issued again). When there are no errors, the Input code will assign the values to the variables, pop the prompt string from the evaluation stack, delete the string if it is a temporary, and advancing the cursor to a next line if not suppressed by a trailing semicolon.

The InputGet code will use sub-code flags to indicate whether there is a prompt string to output and whether to output the “? ” string. The Input code will use sub-code flags to indicate if there is a temporary prompt string that needs deleted and whether the cursor should be kept on the same line.

Normally sub-code flags are only used by the Recreator when generating the original source, and ignored during run-time (so as not to waste execution time checking them). But, considering that this is the INPUT command, a command that is about to stop and wait for an extremely slow user, using time to check sub-code flags is not going to have any significant impact. Next, a more detailed look at how the INPUT command will be executed...

Internal Code – INPUT command (Revised)

Upon considering the resulting translation of the INPUT statement, I realized there is an efficiency that can be made. The prompt string expression only needs to be evaluated one time. The resulting string can be left on the evaluation stack until the end of the INPUT statement. This way, if the prompt is needed again due to an input error, the string expression result is available and does not need to be evaluated again.

This means that the PrintStr or PrintTmp code can not be called because both will pop the string from the evaluation stack and PrintTmp will delete a temporary string. After the values are assigned, then the prompt string can be popped from the evaluation stack and deleted if it is a temporary.

There is one other aspect of the INPUT statement that needs to be considered. There is a built-in looping required to deal with errors. Not having to re-evaluate the prompt string expression means that the loop back jump does not have know where string expression codes begin. Next, what the INPUT translation will look like...

Internal Code – INPUT command

Before the INPUT command can be implemented in the Translator, the translation of the INPUT statement translation must be determined; and before this, how the INPUT command will be executed at run-time. The steps of the INPUT command at run-time are:
  1. Print the prompt string is present
  2. Print the “? ”  prompt (if selected)
  3. Get the input
  4. Parse a value from the input for the data type of the variable
  5. Save the value and repeat for each variable
  6. If there is an error with a value or to many or too little values
  7. Then print “Redo from start” and go back to the first step
  8. Assign each variable to its corresponding value
  9. Move the cursor to the next line (unless there was a semicolon at the end)
The run-time code for the PrintStr code can be called to output the prompt string (step 1). If the prompt is a temporary string, then PrintTmp needs to be called (identical to PrintStr except deletes the temporary string when done). But like all other code that take string operands, the exact code can't be determined by the Translator.

Like with the PRINT statement, there will be separate codes for parsing the input for a particular data type - InputDbl, InputInt, and InputStr (step 3). The values can't be assigned until all the values have been parsed and are valid, so the values need to be saved. Pushing them onto the evaluation stack right after the variable's reference is the logically thing to do.

Once all the values are input, the values can be assigned to the variables (step 8). The run-time code for the Assign data type can be used since the values will be on the stack (variable reference first and then data value). If there no semicolon at the, the cursor needs to be advanced to the next line. The run-time code for Print can be used (step 9).