Showing posts with label Table. Show all posts
Showing posts with label Table. Show all posts

Monday, March 2, 2015

Table Class Hierarchy – LET and Assign Entries

The LET and assign table entries were implemented into the new table class hierarchy.  The sub-string assign entries were not done at this time because they are alternates of the sub-string function entries and these will need to be done at the same time.  The diagram below shows the table sub-class hierarchy for these table entries:
Table
  ├── Command
  │      └── Let [let]
  └── Internal
          └── Assign
                 ├── AssignDbl [assignDbl]
                 ├── AssignInt [assignInt]
                 ├── AssignListDbl [assignListDbl]
                 ├── AssignListInt [assignListInt]
                 ├── AssignListStr [assignListStr]
                 └── AssignStrBase
                            ├── AssignStr [assignStr]
                            └── AssignKeepStr [assignKeepStr]
An AssignStrBase intermediate class was needed because two of the string entry classes have a different recreate function.  The sub-string assign entries will also need this recreate function.  The assign string recreate function was left in place since it is still used by the sub-string assign entries.  For now the recreate function of the AssignStrBase calls this function.

The let recreate function that adds the LET keyword if the Option sub-code is set was made a static function of the Assign intermediate class and renamed to recreate let.  It was made public static to be accessible by the assign string recreate function.  This will be cleaned up when the sub-string assign entries are implemented into the new table class hierarchy.

New Table, Operand and Internal constructors were added with additional arguments needed to support these new classes.  The base virtual table translate function was modified to call the LET translate virtual function directly.  The LET translate function determines the validity of the token.  This was the last use of the translate function pointer member, so it was removed along with its access function.

[branch table commit c575b478ac]

Saturday, February 28, 2015

Table Class Hierarchy – Refactoring (continued)

The two small collection structures (Base Information and Type Information) were moved from the operand source file to the table header file so that they can also be used by the PRINT and INPUT table entry classes.  Unlike with the operand classes, the intermediate Print Item and Input Assign classes are still needed because they contain the common recreate virtual table function for the entry classes.  The intermediate Input Parse class could be removed since these entry classes don't have a recreate function (the blank function in the Internal class is inherited).

As with the operand entry classes, Base Information literal constants were added for the print item, input assign and input parse entries classes, along with the necessary Type Information literal constants.  The input parse table entries previously had a pointer to the Null expression info instance, but now have the same as the input assign entries.  The expression info is not used for these table entries, but the Type Information is used for the data type debug name.  This was done to reduce the number of literal constant definitions needed.

A new table constructor was added that takes the Base Information and Type Information structures, which the Operand and Internal class constructors now call.  This also pushed the call to the append alternate function call up to this Table constructor.  This eliminated the calls to this function in most of the derived classes.  The remaining call is by the Input Assign Double entry class needed because it needs to be assigned to a second primary entry (Input and Input Assign).

[branch table commit a52bd657b2]

Thursday, February 26, 2015

Table Class Hierarchy – Refactoring

The class hierarchies for operand class and the PRINT and INPUT commands were implemented some what differently.  For the operand classes, the integer and string data type entry classes were based on the double data type entry class, where as with PRINT and INPUT, intermediate classes were implemented with the three data type classes based on them.  For their debug names, the operand instances specified theirs, where as the PRINT and INPUT theirs in the constructors.  There was still also an undesirable amount of duplication.

The main and data type parts of the debug names for the operand, PRINT and INPUT entries were separated (more details below).  To reduce some of the duplication in the operand table entry classes, two small structures were added to hold non-common entry data:
Base Information - contains the code, name and table flags for the entry
Type Information - contains the second name (used for the debug data type name) and a pointer to an expression information instance
There is a Base Information structure constant for each main category of operand (constant, variable and variable reference) and there is a Type Information structure constant for each data type (double, integer and string).  The appropriate constants are passed from the operand entry constructor to the Operand class constructor where the values of these structures along with the No Name table flag (see below) and precedence value are passed to the base table constructor.  The names of these structures will probably be renamed as similar structures will be used for the operator and function entries.  The updated class simplified hierarchy is shown in this diagram (compared to initial diagram here):
Table
  └── Operand
          ├── Rem [remCommand, remOperator]
          ├── ConstDbl [constDbl]
          ├── CosntInt [constInt]
          ├── CosntStr [constStr]
          ├── VarDbl [varDbl]
          ├── VarInt [varInt]
          ├── VarStr [varStr]
          ├── VarRefDbl [varRefDbl]
          ├── VarRefInt [varRefInt]
          └── VarRefStr [varRefStr]
A mentioned above, the debug names of these codes were separated into the first and second names.  The data type debug names were changed from Int and Str to % and $ to be consistent with those of the operators and functions (the debug name for Dbl is no character).  For example, VarInt is now Var%.  A similar change was made to Print Item, Input Assign, and Input Parse (for example, PrintDbl and PrintStr are now PrintItem and  PrintItem$).  The expected test results were updated accordingly.

The Hidden table flag was renamed to the No Name flag.  While the Hidden was used in the Convert Integer and Convert Double entries, this flag was not checked anywhere.  The No Name flag is used during entry initialization to prevent entries with this flag from being added to the Name To Entry lookup map since they now contain the main debug name for the entries with operands.  Since the name field is no longer blank for these entries, the parser was changed from checking for a blank name to using the is code with operand access function.   

[branch table commit 1598427319]

Saturday, February 21, 2015

Table Class Hierarchy – INPUT Entries

The INPUT related table entries were put into the  new table class hierarchy.  The diagram below shows the table sub-class hierarchy for the INPUT table entries:
Table
  ├── Command
  │       └── InputCommand
  │                ├── Input [input]
  │                └── InputPrompt [inputPrompt]
  └── Internal
          ├── InputBegin [inputBegin]
          ├── InputBeginStr [inputBeginStr]
          ├── InputAssign
          │        ├── InputAssignDbl [inputAssignDbl]
          │        ├── InputAssignInt [inputAssignInt]
          │        └── InputAssignStr [inputAssignStr]
          └── InputParse
                   ├── InputParseDbl [inputParseDbl]
                   ├── InputParseInt [inputParseInt]
                   └── InputParseStr [inputParseStr]

The intermediate InputCommand, InputAssign and InputParse clases were added to contain the common initializations and functions for their associated entry classes.  The constructor of the InputAssignDbl class required two alternate info arguments since its entry instance is assigned as alternates to both the Input and InputPrompt entries.  The contents of INPUT translate and various INPUT related recreate functions were moved to the virtual functions of these classes (simply renamed).

With these INPUT related table entries created in the new table model, their corresponding entries in the old table entries array were removed along with their code index enumerators.  The alternate initializers for these codes in the temporary alternate info initializer were also removed.

[branch table commit c575b478ac]

Friday, February 20, 2015

Table Class Hierarchy – PRINT Entries

The PRINT related table entries were put into the  new table class hierarchy.  The diagram below shows the table sub-class hierarchy for the PRINT table entries:
Table
  ├── Command
  │       └── Print [print]
  ├── Internal
  │       └── PrintItem
  │                ├── PrintDbl [printDbl]
  │                ├── PrintInt [printInt]
  │                └── PrintStr [printStr]
  └── SpecialOperator
              ├── Semicolon [semicolon]
              └── Comma [comma]

The Command class was already implemented for the table entries of commands that have not been implemented yet.  The Internal class is for codes that are added to the program to support commands, but are not associated with tokens from the input.  The SpecialOperator class are for special operator codes that do not contain arguments.  The intermediate PrintItem class contains those items shared by each of the print data type entries like their recreate function.

The contents of PRINT translate and various print related recreate functions were moved to the virtual functions of these classes (essentially the names of these functions were renamed).  The current print item recreate function was left in place with the PrintItem recreate calling it.  This function is still called by the print function recreate function, which hasn't been converted to the new table model yet.  This is temporary until function entries are put into the new table model. 

The print translate and various recreate functions are in need of refactoring are large and unwieldy.  This will be done later time when the translator and recreator classes are refactored.  With these PRINT related table entries created in the new table model, their corresponding entries in the old table entries array were removed along with their code index enumerators.  The alternate initializers for these codes in the temporary alternate info initializer were also removed.

[branch table commit e495f246cb]

Wednesday, February 18, 2015

Table Class Hierarchy – Operand Entries

The last several commits involved the virtual encode, operand text, and remove table functions.  These virtual functions will only be used by codes that contain operands (a second program word with an index of a dictionary entry).  The table class hierarchy was implemented for these table entries.  The resulting implementation for the operand table sub-class hierarchy is shown in this diagram:
Table
  └── Operand
          ├── Rem [remCommand, remOperator]
          ├── Const [constDbl]
          │    ├── CosntInt [constInt]
          │    └── CosntStr [constStr]
          └── Var [var]
                ├── VarInt [varInt]
                ├── VarStr [varStr]
                └── VarRef [varRef]
                       ├── VarRefInt [varRefInt]
                       └── VarRefStr [varRefStr]

The names in bold are the derived table entry classes used to instantiate the table entries (names shown in brackets).  The italic-bold names are base classes and are not meant to be used to create instances.  Eventually these will contain pure virtual functions preventing instantiation.  Note that some of the derived table entry classes are also used as base classes for related derived table entry classes (Const, Var, and VarRef).

A separate derived table class is needed for each table entry because each will implement a unique run function for execution of that code at run-time.  Unique classes are not necessary for the REM command and REM (') operator because their run functions will do that same thing at execution (which is nothing).

Since the virtual
encode, operand text, and remove table functions are the same for all of these classes, they are implemented in the Operand sub-class and will be inherited by derived entry classes.  The operand recreate function is also common to all of these classes and its contents were moved to the virtual recreate function of Operand class.

For the primary derived table entry classes (Rem, Const, Var, and VarRef), only the constructor is different containing arguments necessary for the associated table entry members.  The table entry instantiations then contain initialization value unique to the entry.  The arguments of each constructor were pushed up the hierarchy for those values that are common.

For the constant sub-classes, each share the same constructor since each needs the same entry member values.  Normally a derived class does not inherit the constructors from its base class, but C++11 allows constructors to be inherited with the using syntax (for example, the ConstInt class contains a using Const::Const; statement to inherit the constructor from the Const class).  This feature should only be used when the derived class contains no additional data members that would not get initialized (which is the case here).

The REM recreate function contents were moved to the Rem class virtual recreate function.  The constant string recreate function contents were moved to the ConstStr class virtual recreate function.  This function was refactored a bit by separating out the replace double quotes with two function (mainly to simplify the recreate function and remove the necessity of a comment that might become stale).

The variable classes were similarly implemented and only the Var and VarRef classes contain constructors with the others inheriting theirs.  TODO comments were added to where the virtual run functions will be put when implemented for all of the derived table entry sub-classes.

Some of these table entries require alternate entries, so a mechanism was implemented to assign these alternates as they can't be automatic like with the operator table entries.  The base Operand constructor contains a reference to an Alternate Item structure instance.  This new simple structure contains a pointer to a primary table entry and an operand index that the entry should be assigned to.

A new table class append alternate function was implemented taking a reference to a Alternate Item structure and is called from the Operand class constructor.  This append alternate function appends the entry pointer (this) to the alternate entry vector of the primary entry for the operand index if the primary entry pointer is not a null pointer (the default if entry is not an alternate).  This functionality will probably be moved up into the base Table class since it will be needed for other table entries classes.

These classes and their instances are defined in the operand.cpp source (previously named basic.cpp) since it contains only sub-classes and entries related to operand table entries.  The sub-classes and instances do not need to be known outside of this source file (no header file is needed).  This will improve compile time since other source files only need to include the main table header file.  The pointers to the instances are added to the static table members via the base Table class constructor that gets called by each entry sub-class constructor.

With these operand table entries are now created in the new table model, their corresponding entries in the old table entries array were removed along with their code index enumerators.  The alternate initializers for these in the temporary alternate info initializer were also removed.

[branch table commit d4aec5bf13]

Sunday, February 15, 2015

Program Reader Class – Call Chain Removal

As mentioned recently, having a chain of function calls is not good object-oriented design because it requires the initial caller to have knowledge of the internal members of each of the subsequent objects in the chain breaking encapsulation.  The table operand text virtual function contained this call chain:
return programLineReader.unit()->dictionary(m_operandType)->string(operand);
Before removing this call change and the equivalent one in the table remove virtual function, some code rearrangement was performed.  This included renaming the Program Line Reader class to simply Program Reader since it reads more than just from a program line (it also access a dictionary).  The Program Reader class and its functions were also moved to their own header and source files.

The get string for operand function was added with an operand type argument.  This eliminated the call chain in the operand text function, which now for clearly reads:
return programReader.getStringForOperand(m_operandType);
To prevent a call chain in this new function (though with one less function call), the get string from dictionary function was added to the program model class with operand type and operand arguments.  An internal read operand function was added for clarity because calling the function operator function internally is the not very self-explanatory this->operand()().

Similarly, the remove reference to operand function with an operand type argument was added for the remove table function along with a remove reference from dictionary program model function with the operand type and operand arguments.

The unit access function, which allowed the call chain in the first place, was no longer used and was removed.  This takes care of the function call chains when reading from the program.  The function call chain when writing to the program will be eliminated next.

[branch table commit 0e6751f023]

Table – Operand Text & Remove Virtual Functions

Like to the encode function, the twelve operand text and remove functions did the same things with different dictionaries.  These were replaced with a single operand text and remove functions.  Both check if the code has an operand.  The operand text function returns an empty string if the code does not have an operand, and the remove function does nothing.

Similar for the initialization of the table entries for the encode function pointers, the operand text and remove function pointer arguments of the secondary table constructor (used for code with no operands) were changed to dummy void pointers so all the table entries didn't need to be modified.

The operand text and remove function pointer arguments were removed from the primary table constructor and the associated function pointers were removed from the table entries of codes with operands.  The operand text function and remove function pointer members were removed from the table class along with their access functions.  And the twelve individual operand text and remove functions were removed.

The tester class function operator function was modified to use the single dictionary pointer access with operand type arguments.  The individual dictionary access functions were now no longer called and were removed.

[branch table commit c5cb6ed943]

Saturday, February 14, 2015

Table – Encode Virtual Function

The six encode functions did the same thing except with a different dictionary, a pointer that was obtained from one of six dictionary access functions.  With the dictionary pointers in an array, a new single dictionary access function was added to the program model with an operand type argument.

A single encode function can be implemented but it needs to obtain the correct operand type for the code being encoded.  The encode function is passed a token pointer and the token contains the pointer to the table entry for the code.  Therefore, an operand type member was added to the table class, but using the token table entry to get the operand type is not the best way to get the operand type (it would be more of a calling chain that is being eliminated).

Since the encode function is virtual, once the new table class hierarchy is implemented, the code with operand class will have its own encode function.  Being a member of the table class, the encode function will have direct access to the operand type member, so there is no need to go through the token anyway.

The table encode virtual function previously called the encode function contained in the encode function pointer member if it was set.  For now this encode function was modified to do what the previous six encode functions did.  If the code has an operand, then the dictionary for the operand type is called to add the entry in the token to the dictionary and the resulting entry index is inserted into the program.  The function call chain is still present (which is in the process of being eliminated).  For other codes, nothing is done, which is what the default encode virtual function will do.

The encode function pointer member was no longer used and was removed along with its access function and the six old encode functions.  To avoid modifying all the table entries (except those with operands), the encode function argument of the table constructor was changed to dummy void pointer (so the encode function pointer initializer in the entries are ignored) and the operand type member is initialized to the No enumerator.

For the codes with operands, a new table constructor was added with an operand type argument and without the encode function pointer argument.  This constructor was made the main constructor with the original constructor calling it.  Since the operand type member can be used to determine if the code has an operand, the Operand table flag was removed and the is code with operand access function was changed to use the new member instead of the flag.

[branch table commit f549771028]

Sunday, February 8, 2015

Program Model Access Refactoring (Part 2)

The next observation was that the program line reader argument of the operand text and remove virtual table functions was accompanied by the program unit pointer argument (needed to access the dictionaries).  Therefore, the program line reader instance can carry the program unit pointer to these virtual functions.

A pointer to the program unit was added to the program line reader class.  The new program model create program line reader function was to pass the pointer to itself to the program line reader constructor.  An access function was added for this pointer.  The program unit pointer argument was removed from all of the operand text and remove functions.  The same changes was made to the token constructor for program words, which also has a program line reader argument.

Unfortunately, the resulting operand text and remove functions have an undesirable calling chain, which existed before, but now was extended another level.  This is undesirable because it breaks encapsulation, meaning that these functions have knowledge of the internals of each class in the chain.  Considered the statements of the REM operand text function:
auto operand = programLineReader();
return programLineReader.unit()->remDictionary()->string(operand);
This function has knowledge that the program line reader has a unit pointer member, that the unit pointer member has REM dictionary member, and that the dictionary has the string function.  These statements are also unusual in that a program word is read from the program line reader, and then passed back to the program line reader through a chain of calls.  This issue will be rectified with the next change.

[branch table commit 66a0db8247]

Saturday, February 7, 2015

Table – Remove Virtual Function

The remove function is called to remove a reference to a dictionary entry for the operand of a code, possibly removing the entry if there are no more references to it.  This function is used by the program model dereference function called when program lines are removed or replaced.  This function had to check if the code had an operand (using the is code with operand access function) before the virtual function could be called.

The program model dereference function was modified to use a program line reader instance.  The remove function function was modified to check if the remove function pointer is not null before calling the remove function of the table entry.  By default, for codes without operands, the remove function will do nothing.

The operand argument of the remove virtual functions was changed to a reference to a program line reader instance.  The remove functions were modified to use the program line reader instance to obtain the operand to pass to the desired dictionary to remove the reference to the item.

[branch table commit b980c95369]

Wednesday, February 4, 2015

Table – Operand Text Virtual Function

The operand text function is called to obtain the text for the operand of a code (for example, the name of a variable or the value of numeric constant).  It is used when a program code for line is decoded into a list of tokens (an then back to the original text of the line).  It is also used for test output.  In both cases it had to check if the code has an operand (using the is code with operand access function) before calling the virtual function.

Similar to the encode functions that control the back insert iterator as needed when the code has an operand, the operand text function should control the advancing of the iterator being used to iterate over the program line if the code has an operand.   The default operand text function does nothing and does not need to advance this iterator.  For now the operand text function was modified to check if the operand text function pointer member is set and then calls the function, otherwise a blank string is returned.

Program Line Reader Class

A regular iterator could have been used with the operand text functions, but the code would look messy (dereference and increment operators would be required).  To make the code more readable and the iterator easier to use, it was encapsulated within a new small Program Line Reader function operator class.

The Program Line Reader class contains two members, the iterator itself and an end iterator used to check for the end the line.  The constructor contains three arguments, the begin iterator of the program code vector, the offset for the start of the program line, and the size of the line.  These values are used to calculate the initial value of the iterator (begin plus offset) and end iterator (iterator plus size).

This class contains three access functions.  The function operator function itself returns the program word pointed to be the iterator and advances the iterator.  The has more words function returns if there are more words in the program line (iterator is not equal to the end iterator).  And there is a previous function for returning the previous word obtained (word before the iterator), which is used by the program model debug text function to get the raw value of the operand to output when there is an operand (the operand text function advances the iterator past this word).

The operand text functions were modified to take a reference to the program line reader instance instead of the operand itself so the codes with operands can advance the iterator as needed (and the other codes without operands do nothing). 

Operand Text Sub-Code Argument

The operand text functions for the variable codes previously added the data type change to the string.  This was only required for test output and was inhibited for normal operation when a program line was decoded into tokens (this character is added later when the tokens are converted into text using the data type of the code table entry).  The sub-code was passed as an argument and when decoding a line, the sub-code was set to a special No Data Type Character sub-code.  The reverse logic made the code less readable.

Eventually the debug/test code will be removed (as much as possible) from the regular application into separate unit test programs.  Adding the data type character was moved from the operand text functions of the variable codes to the program model debug text function.  This was the only use of the sub-code argument, so it was removed from the operand text functions.  The special sub-code enumerator was also removed.

Decoding Into Tokens

The program model decode function, a user of the operand text function, was modified to use the new Program Line Reader class.  It previously created a token from the table entry of the code in the program word.  It then added the sub-code to the token and if the code had an operand, called the operand text function with the No Data Type Character sub-code to prevent adding the data type character and put the resulting string into the string of the token.

Since this section made heavy use of the token, a new token constructor was added to do this work.  The arguments for this new constructor are a pointer to the program unit (for code with operands that need to access the dictionaries) and a reference to the program line reader instance used for iterating over the program line.

The new constructor obtains a program word from the program line reader instance.  The entry member is set to the table entry for the code of the word.  The sub-code member is set to the sub-code of the word.  The operand text function for the entry is called passing the program unit pointer and program line reader.  The string returned is put into the string member.  The string is blank for codes that do not have an operand.

Encoder Tests

The encoder tests did not contain a test where the double data type # character was tested on a variable.  One line in encoder test #1 was modified to contain a variable with the # character on both on the left side (reference) and right side (value) of an assignment.  The expected results for this test were updated accordingly.

[branch table commit ddc2efabbd]

Thursday, January 29, 2015

Table – Encode Virtual Function

The encode mechanism needed to be improved.  The encode function in the program model converts an RPN list to a program line.  For each token in the RPN list, the first program word is generated from the code index and sub-codes of the token and added to the program line.  If the code in the token has an operand (using the is code with operand access function), the second program word is generated by calling the encode function of the table entry to get a index, which is added to the program line.

This mechanism was not making effective use of polymorphism.  A better way is to call the encode function for the table entry, which generates the one or two program words dependent on the requirements of the code in the token (via its table entry).  This was accomplished with several changes.

An encode function was added to the token class since the contents of the token are used for encoding.  The first argument is a pointer to the program unit (an instance of the program model class) needed for the codes with operands to access the dictionaries.  This function also needed access to the program line being encoded.  This was handled by passing a C++11 STL back inserter iterator as the second argument.  This iterator is used to add words to the program line, such as:
*backInserter = <ProgramWord>;
The token encode function then calls the encode function for the table entry.  The arguments include the program unit pointer, back inserter iterator and a pointer to the token.  A plain token pointer is passed (the this pointer).  The token argument of the entry encode functions were changed from a standard shared token pointer to a plain pointer (a shared pointer is not necessary here anyway).  This changes propagated to the dictionary add functions and the dictionary info add element and set element functions.

With the table entry encode functions adding the operand words to the program line directly (via the back inserter iterator), a return value is no longer needed.  The default encode function does nothing since most codes don't require a second operand program word.  For codes with operands (REM, constants, variables, etc.), their encode functions call the dictionary add function whose index return value is added to the program line.

[branch table commit 0e039c280f]

Wednesday, January 28, 2015

Table – Entry Virtual Functions

The implemented commands (LET, REM, PRINT, INPUT, and INPUT PROMPT) each have different initialization values (a code for LET and REM, an option name for the INPUTs, a translate function pointer for all except REM, a recreate function pointer for all but LET, and an encode, operand text and remove functions pointers for only REM).  Creating a single command sub-class constructor to cover these would be messy, and so would creating a different constructor each.

The intention was to replace the functions pointers with virtual pointers, so it was not worth the effort to try and handle these.  Virtual functions were added to the base table class, which temporarily call the function pointer if set (translate and recreate), or just call the function pointer (encode, operand text, and remove).  For the command sub-class, which is only used for commands not yet implemented, the translate virtual function overrides the base class function and throws a "Not Yet Implemented" error.

The is code with operand access function checked if the operand text function pointer was set.  Since the function pointers will be removed, another method for checking if the code has an operand was needed.  A new Operand table flag was added to the REM, REM operator, three constant, and six variable table entries.  This access function was modified to check this flag.

The users of the function pointers (translator and program model) were modified to call the virtual functions.  For the encode, operand text, and remove functions, the program model needs to call the is code with operand function before calling the function.  This resulting code a bit messy and needs to be improved.

[branch table commit c24cf75c90]

Tuesday, January 27, 2015

Table – Command Sub-Class (Initial)

An initial command table entry derived class was implemented consisting of a single constructor taking name and second name string arguments with the second name defaulting to a blank string.  This constructor can be used with both one-word and two-word commands.  It calls the base table constructor passing the two names along with values needed by most commands (Command table flag, precedence of 4 and a pointer to the null expression info instance).

This command constructor is only sufficient for the not yet implemented commands.  For now it also sets the default code (no code), blank option string, and null function pointers.  This class definition was put into a new header file.  In the corresponding source file, instances were created for all of the not yet implemented commands, for example:
static Command Dim("DIM");
The entries for these commands were removed from the static table entry array and the code index enumerators for these commands were removed from the code index enumeration.

The type of the string arguments to the table constructor (name, second name, and option) was changed from a standard string to a C-style string (constant character array pointer) because otherwise, passing a blank string to this constructor required a standard string std::string("") instance, instead of just a blank "" string.

The first time these changes were one, a crash occurred during initialization when trying to add the first of the new command instances because the static table members had not been initialized yet.  Because the new command source file appeared before the table source file in the source file list in the CMake build file, so command instances were initialized before the static table members, but these are needed to initialize the command instances.  To resolve this, the basic sub-directory source files (which will contain the entry instances) were moved to the end of the source file list so that the table source file with the static table members are initialized first.

[branch table commit 97ff351060]

Monday, January 26, 2015

Table – Automatic Two Flag

The table is no longer dependent on the static table entry array so the implementation of the table class hierarchy can begin.  The first sub-class will be for commands.  While investigating the requirements for this sub-class, it was noticed that the Two table flag could be set automatically.  The Two table flag indicates if a command has a two-word form (for example the INPUT and INPUT PROMPT commands).  It is also used for symbol operators that has a two-character form (for example <, <= and <> operators).

The erector class functions were modified to set the Two table flag automatically for these commands and operators.  After a two word command is added to name to entry map, if the first word of the two-word command has an entry, then the Two flag of the one-word entry is set.  Similarly, after a new primary entry is added to the name to entry map, if the entry is a two-character operator, the Two flag is set on the entry for the first character is there is one.  Some additional table entry access functions were added.

The Two table flag was removed from all of the entries.  The Two flag was set on the <> operator, which was not necessary (only the one-character form required this flag).  Not all of the command entries with the flag were covered by parser tests, so additional tests were added to parser test #2 (identifiers).  Not all forms of all operators were covered by the tests.  Translator test #11 (temporary strings) contained an extra set of <= tests, which should have been >= tests.  New translator test #18 was added to cover all operators with all possible data types.

[branch table commit 937c5e3a57]

Sunday, January 25, 2015

Table – Entry Indexes

Up to now, the index for a code that is stored in the program is the index of the table entry in the static table entry array defined in the table source file.  The new table model will not have an array of table entries, but instead will be separate table instances spread among several source files.  The common connection will be through the constructor of the base table class.  This constructor will put pointers to the entries into a standard vector.  As each entry is put into this vector, its index within the vector will be put into an index member of the table entry.

A static index to entry vector was added to the table class along with the index instance member.  The set index and add entry access function was added to set the index of the an entry and add the pointer to the entry to this vector.  A call to this function was added to the erector function.  The index access function was changed to return the value of the index member.  The entry access function was changed to access the index to entry vector instead of the static table entries array.  Both functions were made inline.

The comments were removed from the instance members since they were only stating the obvious, plus the comment for the expression info pointer member stated that a null pointer indicates no expression info even though this no longer applies because all entries are now assigned an expression info instance even it it is the null instance.  This is an example of comments going stale and lying - a good reason for eliminating comments with code explains itself.

[branch table commit 9d74aacf42]

Table – Static Member Access

While refactoring the add to table function and sub-functions into the Erector class functions, one of the desired changes to improve readability was to provide access functions to the static table members.  All of these statements contained the table class scope (Table::) to get to the static member and a table entry pointer.  This meant that table entry access functions could be added that would then access the static table member.

Ideally these access functions would be inline for efficiency.  The reason these changes were not made was that in order to be inline, the table class needs to be defined before the table entry class, but the table entry class needs to be defined before the table class.  Using forward declarations may have solved this issue.  This would not be necessary if the two classes were merged and since they were going to be merged, no effort was used to solve this issue.

With the two classes merged, these access functions could be implemented.  The necessary access functions for the expected data type, alternate, name to entry, and code to entry maps were added and callers were updated accordingly.  The table class scope was eliminated from the erector class functions.  The erector add to code map and two add to expected data type functions were moved back to the table class since both were passed entry pointers.

Several of the existing access functions were renamed for improved readability.  One of the access functions, the alternate count function, was only called from one location in the translator and was used to determine if the unary operator in the token has an alternate binary operator.  This section of code looked like this (note the comments and magic numbers):
// check if code has a binary operator
if (m_token->alternateCount(1) > 0) {
    m_token->setFirstAlternate(1);  // change to binary operator
}
This function was renamed to the has binary operator function.  Several constant expressions (integers) were added for predefined operand indexes for use with the various alternate access functions so magic numbers are not used.  With the renamed access function and constant expressions, the resulting code is much more readable (note the absence of comments):
if (m_token->hasBinaryOperator()) {
    m_token->setToFirstAlternate(BinaryOperator);
}
[branch table commit 03140858b0]

Saturday, January 24, 2015

Table – Single Class

The table class, with static members, and the table entry class, with entry (instance) members, were combined into a single class, named the Table class.  The former table entry constructor (which had no body) was moved to the table source file and a call to an Erector instance was added to add the needed info to the static table table members.

The iteration of the entries in the static table entry array that called an Erector instance for each entry was removed from the default constructor since the table entry constructor now does this.  The only statements remaining in this constructor are the initialization of the other alternates.  This constructor along with the single table instance will remain to initialize these other alternates until this can be reimplemented in the new class hierarchy.

With these constructors in place, the class hierarchy can be implemented one derived class at a time.  As each is implemented, the entries will be removed from the static array along with the enumerator from the entry.

The method previously used to disable the copy constructor and copy assignment was to make them private so they are not accessible, at least from outside the class.  C++11 has a better method of accomplish this using the new delete feature.  C++11 also has move constructors and assignments, so these also needed to be deleted.  For example, the copy constructor and assignments are disabled like this:
Table &operator=(const Table &) = delete;
Table(const Table &) = delete;
Some other minor changes were made.  All instances of variables named operand index (mostly arguments of access functions) were renamed operand. This was already done in the Erector class.  Several redundant comments were also removed.

[branch table commit 9153b17e5e]

Table – Add To Table Refactoring (Part 3)

The add to table function and all the functions it calls share several variables, which required them to be passed between the functions.  Enter the new Erector class to contain these functions and shared variables.  This class is a function operator class with a constructor that takes a table entry pointer, and the function operator function for adding the element to the table (static member variables).  This class was made a friend class of the table and table entry classes to make private member functions accessible.

The shared members of the Erector class include the table entry pointer being added, table entry pointer to the primary entry, table entry pointer to an alternate entry, and an operand index used for iterating and used by multiple functions.  Most of the member functions were declared in the header file after the class definition to not clutter up the class definition.  Each of these were declared inline since each is called once.  Two functions called multiple times were put into the source file.

Many of the functions were renamed again to better explain what they do.  There was addition refactoring moving statements up and done the functions during this renaming.  Not widely known (at least is wasn't to me) is that C++ contains alternate representations for the logical operators, for example and for &&, or for ||, and not for !.  To make the code a little more readable, the not operator was used since the ! operator can be head to see.

The main function was restructured to eliminate the need of the Done structure exception.  This unusual mechanism was used as sort of a goto to cause an exit from anywhere.  The elimination of this exception-exit mechanism was now possible since the sub-functions no longer returned table entry pointers (which are now member variables and set directly) opening up the use of boolean return values.

[branch table commit f199936e70]