While modifying the translator routines to throw exceptions, it was noticed that some minor improvements could be made. The first of these is with calls to the get token function. There was a similar pattern to most of the calls to this function, where the call was in a try block and for caught errors, the error was set to an appropriate error.
An error status argument was added to the get token function. The caller puts its desired error status to be returned when the parser returns an Unknown Token. With this change, the caller no longer needs to catch errors from the get token function call. Several of the callers need the parser error to be thrown as is, so if the error status argument is a null status, the parser error is thrown as is. The first status enumerator was assigned to a value of one so that a null status is not one of the existing enumerators.
[branch misc-cpp-stl commit 950d3cf9ed]
Thursday, November 27, 2014
Translator Exceptions – Expressions
The get expression function was modified to throw errors. The return type was removed since a no exception return now indicates success. The temporary error tokens for errors no longer need to be created. The Done status that was previously returned for success was no longer used, so this status enumerator was removed.
All callers of the get expression function were modified for an error being thrown, which for the most part meant catching errors instead of looking for an error return status. However, there was an issue with how errors were processed when an unexpected unary operator token appeared.
When an unexpected unary operator appeared, get expression returned an "expected binary operator or end-of-statement" error along with the unary operator token. When another error was appropriate, the caller essentially ignored this error when it a unary operator, and threw the appropriate error. Now that get expression throws an error, there is no token returned, so callers cannot look for a unary operator token. The callers were were modified to look for this error and then throw the appropriate error.
[branch misc-cpp-stl commit 697a0d25d8]
All callers of the get expression function were modified for an error being thrown, which for the most part meant catching errors instead of looking for an error return status. However, there was an issue with how errors were processed when an unexpected unary operator token appeared.
When an unexpected unary operator appeared, get expression returned an "expected binary operator or end-of-statement" error along with the unary operator token. When another error was appropriate, the caller essentially ignored this error when it a unary operator, and threw the appropriate error. Now that get expression throws an error, there is no token returned, so callers cannot look for a unary operator token. The callers were were modified to look for this error and then throw the appropriate error.
[branch misc-cpp-stl commit 697a0d25d8]
Wednesday, November 26, 2014
Translator Exceptions – Tokens
The get token function used to get the next token from the parser was modified to throw errors. The return type was removed since a no exception return now indicates success. The temporary error token for an error no longer needs to be created. The Good status that was previously returned for success was no longer used, so this status enumerator was removed.
All the callers of the get token function were modified for errors being thrown, which mostly included catching the error and throwing the appropriate error for the Unknown Token error. The get operand function just passes the error on to its caller (In this case, in addition to an Unknown Token error, a number constant error could be returned for non-reference token requests).
The get expression function was modified to catch the error from the get token function, obtain the error status and create an error token. Th error token won't be necessary once this function is modified to throw errors (which is now the only function remaining now modified yet to throw errors).
In the LET translate function where the token after a reference token is not a comma or equal character, the token on top of the done stack was checked to see if it has the sub-string flag set, and if is does this item (a sub-string assignment function) is popped. This is not necessary since once an error is thrown out of the translator, the translator instance is deleted along with the done stack.
[branch misc-cpp-stl commit 217de6d02c]
All the callers of the get token function were modified for errors being thrown, which mostly included catching the error and throwing the appropriate error for the Unknown Token error. The get operand function just passes the error on to its caller (In this case, in addition to an Unknown Token error, a number constant error could be returned for non-reference token requests).
The get expression function was modified to catch the error from the get token function, obtain the error status and create an error token. Th error token won't be necessary once this function is modified to throw errors (which is now the only function remaining now modified yet to throw errors).
In the LET translate function where the token after a reference token is not a comma or equal character, the token on top of the done stack was checked to see if it has the sub-string flag set, and if is does this item (a sub-string assignment function) is popped. This is not necessary since once an error is thrown out of the translator, the translator instance is deleted along with the done stack.
[branch misc-cpp-stl commit 217de6d02c]
Tuesday, November 25, 2014
Translator Exceptions – Operators
The process operator function called by the get expression function was modified to throw errors. This function returned Done status for a token that is not an operator, Good status for a successfully processed unary or binary operator, or an error status. Since errors on now thrown, the return type was changed to a boolean, true for success and false for not an operator.
The process done stack top function is used to pop an item from the done stack and add a conversion code to the output if needed or report an error if the item can't be converted. This function used by the process final operand, INPUT translate, and LET translate functions was modified to throw the error and its return type was removed. These callers were modified to just call the function and any error thrown will the passed to their caller.
Similarly, the process operator function was changed to just call the process final operand function, and its error is not caught passing any error thrown up to its caller, which is the get expression function.
The process first operand function was called to process the first operand of a binary operator, and push the unary or binary operator to the hold stack. At first it was also modified to throw errors (again from the process done stack top function), but this function ended up being only a few lines, and since is only called by the process operator function, its code was just moved into the process operator function eliminating the separate function.
The get expression was temporarily modified to catch errors from the process operator function where the status is obtained from the thrown error, and an error token is created from the error column and length. The error status and the token is returned as before. This won't be necessary once get expression is modified to throw errors.
[branch misc-cpp-stl commit cf45a8e393]
The process done stack top function is used to pop an item from the done stack and add a conversion code to the output if needed or report an error if the item can't be converted. This function used by the process final operand, INPUT translate, and LET translate functions was modified to throw the error and its return type was removed. These callers were modified to just call the function and any error thrown will the passed to their caller.
Similarly, the process operator function was changed to just call the process final operand function, and its error is not caught passing any error thrown up to its caller, which is the get expression function.
The process first operand function was called to process the first operand of a binary operator, and push the unary or binary operator to the hold stack. At first it was also modified to throw errors (again from the process done stack top function), but this function ended up being only a few lines, and since is only called by the process operator function, its code was just moved into the process operator function eliminating the separate function.
The get expression was temporarily modified to catch errors from the process operator function where the status is obtained from the thrown error, and an error token is created from the error column and length. The error status and the token is returned as before. This won't be necessary once get expression is modified to throw errors.
[branch misc-cpp-stl commit cf45a8e393]
Sunday, November 23, 2014
Translator Exceptions – Parentheses Tokens
The process parentheses token function used to translate tokens with parentheses token (arrays and user functions) for the get operand function was modified to throw errors. This function only returned a Good status or an error status, so a return value was no longer needed. Like the process internal function function, the get expression call was changed to throw an error if an error status is return, which is immediately caught. This simulates the get expression function throwing an error, which has not been modified yet to throw errors.
Unrelated to this function, the comments for the other functions modified were updated to reflect the changes made so far, which was missed when these functions were changed. The new expression error status function added for the process internal function function was moved to the support functions section of the source file.
[branch misc-cpp-stl commit 4f03c8bd77]
Unrelated to this function, the comments for the other functions modified were updated to reflect the changes made so far, which was missed when these functions were changed. The new expression error status function added for the process internal function function was moved to the support functions section of the source file.
[branch misc-cpp-stl commit 4f03c8bd77]
Saturday, November 22, 2014
Translator Exceptions – Internal Functions
The process internal function function used to translate internal function tokens for the get operand function was modified to throw errors. Some of the changes made in the failed attempt to add exceptions throughout the translator routines around the get operand call used for sub-string assignments ended up in the code during the last commit. This did not affect the functionality (since the regression tests had passed, it wasn't noticed).
The expression error status private helper function was added to determine the error status depending on whether at the last operand of the internal function, if the internal function has multiple arguments and if the bad token is a unary operator. This function is called in three locations.
Since all errors are thrown, there was no longer a need for a return value. The unary operator local variable was no longer needed and was removed. The status and expected data type local variable declarations were moved closer to where they are used. The status variable can be removed once the get expression function is modified to throw errors.
[branch misc-cpp-stl commit 640255514d]
The expression error status private helper function was added to determine the error status depending on whether at the last operand of the internal function, if the internal function has multiple arguments and if the bad token is a unary operator. This function is called in three locations.
Since all errors are thrown, there was no longer a need for a return value. The unary operator local variable was no longer needed and was removed. The status and expected data type local variable declarations were moved closer to where they are used. The status variable can be removed once the get expression function is modified to throw errors.
[branch misc-cpp-stl commit 640255514d]
Translator Exceptions – Operands
The get operand function used to get an operand was modified to throw errors. The command routines either returned an error or a Done status, so once they were modified to throw errors, there was no need to return anything. In addition to errors, the get operand function returned a Good status representing successfully getting an operand or a Done status representing no operand token (an operator or command).
The return value of the get operand function was changed to a boolean where true represents successfully getting an operand and false representing no operand. When a reference operand is requested this function will not return a false status, it will just throw an error. So for the process internal function, LET translate, and INPUT translate routines, it is not necessary to test the return value since these only request reference operands.
There were three locations in the get operand function where errors were returned that popped the token on top of the hold stack before returning. This was intended to prevent memory leaks. This wasn't necessary since the translator cleans up the stack when the translator goes out of scope, so these pop calls were removed.
One of the errors for define function identifiers with parentheses tokens added the length of the token to the column to point the error to the parentheses of the token. The token class add length to column access function was used for this. Instead of using this access function (the only caller), the token length is added to the column when the token error instance is created and thrown. This access function was removed.
[branch misc-cpp-stl commit 640255514d]
The return value of the get operand function was changed to a boolean where true represents successfully getting an operand and false representing no operand. When a reference operand is requested this function will not return a false status, it will just throw an error. So for the process internal function, LET translate, and INPUT translate routines, it is not necessary to test the return value since these only request reference operands.
There were three locations in the get operand function where errors were returned that popped the token on top of the hold stack before returning. This was intended to prevent memory leaks. This wasn't necessary since the translator cleans up the stack when the translator goes out of scope, so these pop calls were removed.
One of the errors for define function identifiers with parentheses tokens added the length of the token to the column to point the error to the parentheses of the token. The token class add length to column access function was used for this. Instead of using this access function (the only caller), the token length is added to the column when the token error instance is created and thrown. This access function was removed.
[branch misc-cpp-stl commit 640255514d]
Translator Exceptions – Commands
The routines that process commands were the next modified to throw exceptions. This included the get commands routine used to get command statements separated by colons. For now, if the two calls to the get token function return an error (not good status), the appropriate error is thrown. The get token function will also be modified to throw errors soon. Since get commands now throws errors, it no longer needs to return a status so the return type was removed (along with the local status variable).
The process command routine handles the processing of one command and was modified to throw exceptions. It calls a specific translate function for a command or the LET translate function if the first token is not a command. The LET, PRINT and INPUT translate functions were also modified to throw exceptions. The status return type was also removed and if statement surrounding the call to process command in get commands was removed (which will cause thrown exceptions to be thrown up its caller - the translator function operator function).
In the translator function operator function, a status is no longer returned from the get commands function, so assignment of the local status variable was removed. And thrown exceptions are passed up to the caller of the function operator function (which will catch the errors). For a successful return, the local status variable is set to Done. This is temporary until the get expression function is also modified to throw exceptions.
The LET, PRINT and INPUT translate functions were restructured a bit. Local variable declarations were moved to where the variables are first used. Some of the error checking if statements were rearranged to ease the handling of errors (when the lower functions are modified to throw exceptions). These changes came from the failed total translator exception changes. The checks for the end-of-statement were also moved to a more logical place in each of these routines.
[branch misc-cpp-stl commit 7217ce58c6]
The process command routine handles the processing of one command and was modified to throw exceptions. It calls a specific translate function for a command or the LET translate function if the first token is not a command. The LET, PRINT and INPUT translate functions were also modified to throw exceptions. The status return type was also removed and if statement surrounding the call to process command in get commands was removed (which will cause thrown exceptions to be thrown up its caller - the translator function operator function).
In the translator function operator function, a status is no longer returned from the get commands function, so assignment of the local status variable was removed. And thrown exceptions are passed up to the caller of the function operator function (which will catch the errors). For a successful return, the local status variable is set to Done. This is temporary until the get expression function is also modified to throw exceptions.
The LET, PRINT and INPUT translate functions were restructured a bit. Local variable declarations were moved to where the variables are first used. Some of the error checking if statements were rearranged to ease the handling of errors (when the lower functions are modified to throw exceptions). These changes came from the failed total translator exception changes. The checks for the end-of-statement were also moved to a more logical place in each of these routines.
[branch misc-cpp-stl commit 7217ce58c6]
Friday, November 21, 2014
Translator Exceptions – Top-Level
Several convenience functions were added to the Token Error structure to make it syntactically easier to use. These include a function operator function with no arguments for returning the status of the error, a function operator function with a status argument for checking if the error status is the passed status, and an assignment operator function taking a status value to assign to the error status.
The translator function operator function was modified to throw errors instead of setting a local status variable, which is then used to throw the error at the end of the function. Eventually the get expressions and get commands functions will throw exceptions for errors and the local status variable won't be necessary.
The try block in the tester parse input function was reformatted where the try-catch blocks were moved outside of the forever loop to the function block. The return statement in the catch block could then be removed.
[branch misc-cpp-stl commit c639347b07]
The translator function operator function was modified to throw errors instead of setting a local status variable, which is then used to throw the error at the end of the function. Eventually the get expressions and get commands functions will throw exceptions for errors and the local status variable won't be necessary.
The try block in the tester parse input function was reformatted where the try-catch blocks were moved outside of the forever loop to the function block. The return statement in the catch block could then be removed.
[branch misc-cpp-stl commit c639347b07]
Translator Exceptions – Development Strategy
The next incremental change was initially difficult to see for adding exception throws throughout the translator routines. Starting at the bottom by changing the get token function to throw exceptions was problematic because all callers would have to catch the errors and create an error token to hold the column and length of the error. Starting at the top by changing both the get expressions (used for testing) and get commands functions to throw exceptions was problematic because all functions in between would also need to be modified. An attempt to change the entire translator was made.
After the code was modified and corrected for compile errors, the tests were run, but there were many problems, which was not unexpected considering the large number of changes made. Instead of trying to debug, the changes were committed to a temporary work branch (though not pushed to the official GitHub repository). This is a scheme to use git to temporary save work:
After the code was modified and corrected for compile errors, the tests were run, but there were many problems, which was not unexpected considering the large number of changes made. Instead of trying to debug, the changes were committed to a temporary work branch (though not pushed to the official GitHub repository). This is a scheme to use git to temporary save work:
git checkout -b work (create a temporary work branch)This saved the changes of the failed attempt and restored the original files. Changes from the work branch could now be transferred to the working directory piecemeal. For example, several changes were made to the Token Error structure in the token header file (details in the next post). For more details on using this scheme, click Continue...
git commit -a (stages all changed files and commits them)
git checkout -b misc-cpp-stl (restore all files before changes)
Sunday, November 16, 2014
Token Errors (Minor Refactoring)
The plan is to modify the translator routines to throw error exceptions when an error is detected. Errors consist of a status, column and length. For translator errors, the column and length will always be obtained from a token, so it made sense to add a constructor that takes status and token pointer arguments.
The Error structure was a plain structure with no constructors, so a default constructor is generated by the compiler taking arguments for the three member variables. Once a constructor is added, this default constructor is no longer generated, so one was added. The constructor taking status and token pointer arguments was also added. Since the structure now has constructors, the member variables were renamed with the member "m_" prefix.
The Error structure was defined in the main header file. This header file does not have access to the token header so that the new constructor can retrieve the column and length from the token, and an include couldn't be added for the token header because the token header already includes this main header file. The Error structure was therefore moved to the token header file. The name Error was a little generic so this structure was renamed to the more appropriate Token Error.
[branch misc-cpp-stl commit 97ce3592c3]
The Error structure was a plain structure with no constructors, so a default constructor is generated by the compiler taking arguments for the three member variables. Once a constructor is added, this default constructor is no longer generated, so one was added. The constructor taking status and token pointer arguments was also added. Since the structure now has constructors, the member variables were renamed with the member "m_" prefix.
The Error structure was defined in the main header file. This header file does not have access to the token header so that the new constructor can retrieve the column and length from the token, and an include couldn't be added for the token header because the token header already includes this main header file. The Error structure was therefore moved to the token header file. The name Error was a little generic so this structure was renamed to the more appropriate Token Error.
[branch misc-cpp-stl commit 97ce3592c3]
Translator – Exceptions (Top-Level)
The goal of the next step is to modify the translator to throw errors instead of returning an RPN list containing an error. This will be done in steps starting at the top-level of the translator in the function operator function with a couple of other minor improvements to the code.
The first minor improvement was made to the Error Item class that holds information about an error in the program (includes type, line number, column, length and error status). The is empty function that checks if the error type is none (no error) was replaced with the explicit operator bool function, which allows an error item to be checked for an error without a named function (this function is called when a boolean is expected and an error item instance is provided):
The tester translate input routine was modified to catch an error in a try block. This routine no longer needs to check if RPN list has an error, and if it did, retrieve the error information to create a local error instance and print the error. Now upon a caught error, it simply prints the error. It also returns an empty RPN list that the caller uses to detect an error.
The program model update line routine was modified to catch an error in a try block. For an error, the local error item is set to an error with the info in the thrown error. If there is no error then the error item will not contain an error (the default constructor sets the error type to none).
To detect a change, the update line routine compared the new RPN list to the current RPN list decoded from the program. The lists were not equal if either contained an error. The current RPN list is empty for a line with an error, but the decode routine does not set the error variables. Now that the RPN list does not have an error status, so the error item also needs to be checked when checking if the line changed. The RPN error variables are no longer used and were removed along with their access functions. The check for errors in the RPN list equality operator function was also removed.
The final improvement made was to changed the RPN list argument of the encode routine from a constant reference to an rvalue reference. All calls to the encode routine no longer needs the RPN list after the call, so it can be moved. Since the arguments of these calls were not a temporary instance, the local RPN list variable needs to moved using std::move.
[branch misc-cpp-stl commit 52359711e7]
The first minor improvement was made to the Error Item class that holds information about an error in the program (includes type, line number, column, length and error status). The is empty function that checks if the error type is none (no error) was replaced with the explicit operator bool function, which allows an error item to be checked for an error without a named function (this function is called when a boolean is expected and an error item instance is provided):
if (!errorItem.isEmpty()) → if (errorItem)At the end of the translator function operator function, if the status is not Done, the RPN list was cleared and its error member variables were set (column, length and status). This was changed to throw an Error structure with the status, token column and token length. The RPN list no longer needs to be cleared since it will be cleared when the temporary translator instance goes out of scope.
The tester translate input routine was modified to catch an error in a try block. This routine no longer needs to check if RPN list has an error, and if it did, retrieve the error information to create a local error instance and print the error. Now upon a caught error, it simply prints the error. It also returns an empty RPN list that the caller uses to detect an error.
The program model update line routine was modified to catch an error in a try block. For an error, the local error item is set to an error with the info in the thrown error. If there is no error then the error item will not contain an error (the default constructor sets the error type to none).
To detect a change, the update line routine compared the new RPN list to the current RPN list decoded from the program. The lists were not equal if either contained an error. The current RPN list is empty for a line with an error, but the decode routine does not set the error variables. Now that the RPN list does not have an error status, so the error item also needs to be checked when checking if the line changed. The RPN error variables are no longer used and were removed along with their access functions. The check for errors in the RPN list equality operator function was also removed.
The final improvement made was to changed the RPN list argument of the encode routine from a constant reference to an rvalue reference. All calls to the encode routine no longer needs the RPN list after the call, so it can be moved. Since the arguments of these calls were not a temporary instance, the local RPN list variable needs to moved using std::move.
[branch misc-cpp-stl commit 52359711e7]
Translator – Function Operator
The Translator class has a single purpose, to task a BASIC input string and create an RPN list representation of the BASIC code. This is similar to the Parser, Tester, and Recreator classes, which were already changed to be function operator classes. This started with renaming the translate function to operator().
Like the recreator where a temporary instance is used, the translator can be used in the same way except that the input string is passed to the constructor so that it can be used to instance the parser (which lives throughout the translation). The parser no longer needs to be instanced at the beginning and reset before returning in the function operator function. Since only a temporary instance is needed to translate, the translator member pointers in the tester and program model classes were removed.
The clean up function was called when the translator returned an error, which deleted the hold and done stack items, cleared the RPN output list and reset the pending parentheses token pointer. Now at the end of a translation, including when an error is detected, the temporary translator instance goes out of scope, all all these actions occur automatically except for the clearing of the output list (since it is moved to the caller upon return). This clean up function was removed. For an error, the output list is cleared.
[branch misc-cpp-stl commit b597b5b0a7]
Like the recreator where a temporary instance is used, the translator can be used in the same way except that the input string is passed to the constructor so that it can be used to instance the parser (which lives throughout the translation). The parser no longer needs to be instanced at the beginning and reset before returning in the function operator function. Since only a temporary instance is needed to translate, the translator member pointers in the tester and program model classes were removed.
The clean up function was called when the translator returned an error, which deleted the hold and done stack items, cleared the RPN output list and reset the pending parentheses token pointer. Now at the end of a translation, including when an error is detected, the temporary translator instance goes out of scope, all all these actions occur automatically except for the clearing of the output list (since it is moved to the caller upon return). This clean up function was removed. For an error, the output list is cleared.
[branch misc-cpp-stl commit b597b5b0a7]
Saturday, November 15, 2014
Program Model – Standard Strings
To complete the transition of the program model to the STL, all of the strings were changed to standard strings. This included the return value of the line text function, the text member of the line info structure, and an argument of the update line function (where an rvalue reference was used since the caller no longer needs the string passed so it is moved to the function).
The QStringList argument of the update function was changed to a std::vector<std::string> (the STL has no string list class) rvalue reference type (the caller no longer needs the vector passed so it can be moved to the update function). The update function was defined as a public slot, but was no longer being used as a slot, so it was changed to a regular public function.
All callers to the modified functions were modified accordingly. This included the translate function of the translator where its input argument was already being converted to a standard string to pass to the parser constructor. There were four functions that put function pointers into a temporary variable. These were changed to if-statement scoped variables using the auto type for convenience. This concludes work on the program model.
[branch misc-cpp-stl commit 2f7a0bb119]
The QStringList argument of the update function was changed to a std::vector<std::string> (the STL has no string list class) rvalue reference type (the caller no longer needs the vector passed so it can be moved to the update function). The update function was defined as a public slot, but was no longer being used as a slot, so it was changed to a regular public function.
All callers to the modified functions were modified accordingly. This included the translate function of the translator where its input argument was already being converted to a standard string to pass to the parser constructor. There were four functions that put function pointers into a temporary variable. These were changed to if-statement scoped variables using the auto type for convenience. This concludes work on the program model.
[branch misc-cpp-stl commit 2f7a0bb119]
Program Model – Line Info List
The program model contains a list of information for each line in the program code vector including the offset into the code vector, the size of the line, and if the line has an error, the error index for the line and its original text. This member list is an instance of the Line Info List class also defined in the Program Model class.
The Line Info List class is another class that derived from a container class (QList). This class was changed to instead contain the standard vector as a member (QList is implemented as an array internally similar to a vector). The existing adjust (private), replace, insert and remove at functions were modified accordingly. The remove at function was renamed to erase for consistency with STL naming conventions.
Necessary vector access functions were added to the Line Info List class including bracket operator for element access, constant bracket operator for constant element access, size of vector, and clear vector. Since the bracket operator is used frequently to access the offset and size line info structure member variables, specific offset and size element access functions were added taking a line number argument.
The STL convention is to use size to represent the number of items compared to the Qt convention is use count. Many of the variables and functions were naming using the Qt convention. The variables in the program model functions were changed to the STL size name. The program model also contained two temporary access functions (line offset and line size) that were not being used and were removed.
[branch misc-cpp-stl commit fd24923d76]
The Line Info List class is another class that derived from a container class (QList). This class was changed to instead contain the standard vector as a member (QList is implemented as an array internally similar to a vector). The existing adjust (private), replace, insert and remove at functions were modified accordingly. The remove at function was renamed to erase for consistency with STL naming conventions.
Necessary vector access functions were added to the Line Info List class including bracket operator for element access, constant bracket operator for constant element access, size of vector, and clear vector. Since the bracket operator is used frequently to access the offset and size line info structure member variables, specific offset and size element access functions were added taking a line number argument.
The STL convention is to use size to represent the number of items compared to the Qt convention is use count. Many of the variables and functions were naming using the Qt convention. The variables in the program model functions were changed to the STL size name. The program model also contained two temporary access functions (line offset and line size) that were not being used and were removed.
[branch misc-cpp-stl commit fd24923d76]
Program Code – Standard Vector
The Program Code class holds the code of the program in a vector. The vector consists of program words. This class was derived from the QVector, which exposes all of base functions. This not the best object-oriented design practice, and was redesigned to instead contain a standard vector member. The program words are defined by the Program Word class, which consists of various access functions to access the code, sub-code and operand components of program word.
Several functions are needed to access the member vector including the begin iterator, end iterator, empty status, size, clear vector, element access bracket operator ([]) and the emplace back functions. These functions simply pass through to the code vector member. The main program code insert line, remove line, and replace line access functions were modified to use standard vector functions (insert and erase or using the direct standard copy) to manipulate the code vector instead of the raw memory move function previously used.
Using the vector functions simplified the code, but since there is no function to replace part of the vector with a different size part, the replace line still contains various checks and operations depending on size of the old and new lines. For an empty new line, the remove line function is called as before. For a same size or larger new line, the part of the new line that will fit in the space of old line is copied. For a larger new line, the rest of the new line is then inserted. For a smaller new line, the new line is copied, and the remainder of the old line is erased.
The debug text, dereference and decode functions of the program model previously obtained a pointer to the first word of the program line by adding its offset to the the raw data access function. These were changed to obtain a vector iterator to the line by adding the line offset to the begin iterator of the program code vector. The C++11 auto type was used to define these iterators, which is simpler then using std::vector<ProgramWord>::const_iterator or the ProgramCode::const_iterator alias added to the program code class.
The encode function of the program model previously created a sized vector for the new line (using a constructor taking a size argument), and each word was set to the instruction or operand information from the RPN list. This was replaced by starting with an empty vector and using the emplace back template function for each instruction and operand word. The set instruction and set operand functions of the program word class were replaced with corresponding constructors needed for the emplace back function. The size constructor was removed.
The Program Word and Program Code classes were moved to a new header file since the program model header file. The insert line, remove line, and replace line functions were kept as in-line functions in the class definition. Each of these functions are only called once, so in-lining is appropriate. This header file did not show up in the project file list in QtCreator (the project built fine) because there was no associated source file. A new headers variable was added to the CMake build file with this new header file and the main program target was made dependent on this variable so that QtCreator knows about this new header file.
[branch misc-cpp-stl commit c7080421cb]
Several functions are needed to access the member vector including the begin iterator, end iterator, empty status, size, clear vector, element access bracket operator ([]) and the emplace back functions. These functions simply pass through to the code vector member. The main program code insert line, remove line, and replace line access functions were modified to use standard vector functions (insert and erase or using the direct standard copy) to manipulate the code vector instead of the raw memory move function previously used.
Using the vector functions simplified the code, but since there is no function to replace part of the vector with a different size part, the replace line still contains various checks and operations depending on size of the old and new lines. For an empty new line, the remove line function is called as before. For a same size or larger new line, the part of the new line that will fit in the space of old line is copied. For a larger new line, the rest of the new line is then inserted. For a smaller new line, the new line is copied, and the remainder of the old line is erased.
The debug text, dereference and decode functions of the program model previously obtained a pointer to the first word of the program line by adding its offset to the the raw data access function. These were changed to obtain a vector iterator to the line by adding the line offset to the begin iterator of the program code vector. The C++11 auto type was used to define these iterators, which is simpler then using std::vector<ProgramWord>::const_iterator or the ProgramCode::const_iterator alias added to the program code class.
The encode function of the program model previously created a sized vector for the new line (using a constructor taking a size argument), and each word was set to the instruction or operand information from the RPN list. This was replaced by starting with an empty vector and using the emplace back template function for each instruction and operand word. The set instruction and set operand functions of the program word class were replaced with corresponding constructors needed for the emplace back function. The size constructor was removed.
The Program Word and Program Code classes were moved to a new header file since the program model header file. The insert line, remove line, and replace line functions were kept as in-line functions in the class definition. Each of these functions are only called once, so in-lining is appropriate. This header file did not show up in the project file list in QtCreator (the project built fine) because there was no associated source file. A new headers variable was added to the CMake build file with this new header file and the main program target was made dependent on this variable so that QtCreator knows about this new header file.
[branch misc-cpp-stl commit c7080421cb]
Subscribe to:
Posts (Atom)