#============================================================ # PROGRAMMER:........ William L. Bahn # USERID:............ WBAHN # COURSE:............ CSCI-410 # TERM............... FALL 2013 # ASIGNMENT:......... PY01 # FILENAME:.......... PY01_Hints.txt # PYTHON VERSION:.... 3.3.0 #============================================================ # THIS FILE CONTAINS EVERYTHIGN EXCEPT THE CODE PORTION OF # THE INSTUCTOR'S PARTIAL SOLUTIONS #============================================================ # PROGRAMMER:........ William L. Bahn # USERID:............ WBAHN # COURSE:............ CSCI-410 # TERM............... FALL 2013 # ASIGNMENT:......... PY01 # FILENAME:.......... py01_1.py # PYTHON VERSION:.... 3.3.0 #============================================================ #============================================================ # Instructor's PARTIAL Solution # # This series of files (py01_?.py) represents the steps I # went through as I implemented this program. You'll notice a # strong dose of incrementalism (a.k.a., baby steps). #============================================================ # The first thing that has to happen is that the input file # has to be successfully opened and its contents read. To test # this, we will simply open the file and print the contents to # the screen one line at a time. # # Since it was not specified how the program should behave if # it encounters a problem, anything reasonable is acceptable. # Perhps the most sensible thing to do in most cases is to # issue some type of descriptive error message and exit the # program. It might make sense, in some cases, to issue a # warning and continue processing. # # Since Python is pretty good about crashing gracefully if the # program throws an unhandled exception, we will ignore, for # now, error checking. This is NOT a practice that is really # recommended, but the point here is to show the processing # steps. We'll deal with error handling at the end and, in the # future, apply it along the way more like it should be done. # # In order to keep things moving, one of the short *.hack files # from ECS-05, namely add.hack, was copied over and renamed # machine.hack. When this program was run, it opened the file # and printed the contents to the screen, but there were was # a blank line between each line. A bit of research reveals # that the print() function, by default, adds a newline to each # line it prints and that when a file is iterated through using # the for..in construct that the newline characters are kept as # part of the line. Adding the to the print() call # cured this. # #============================================================ # PROGRAMMER:........ William L. Bahn # USERID:............ WBAHN # COURSE:............ CSCI-410 # TERM............... FALL 2013 # ASIGNMENT:......... PY01 # FILENAME:.......... py01_2.py # PYTHON VERSION:.... 3.3.0 #============================================================ #============================================================ # Instructor's PARTIAL Solution # # This series of files (py01_?.py) represents the steps I # went through as I implemented this program. You'll notice a # strong dose of incrementalism (a.k.a., baby steps). #============================================================ # The next step is simply to modify the program so that the # contents of the input file are successfully sent to the # output file. This will ensure that we can actually access # a file for writing and write to it. # # To open the file we use the open() function again, but # this time with a 'w' mode string. # # To direct the output to the file, we can use another option # in the print() call to send the output to a file. This option # is the option. # # While the program seemed to run and did, infact, create the # output file, it was empty. A bit of experimentation revealed # that the problem appears to be that the IDLE IDE can't # actually write output to a file using the print() function. # # Trying to run the program from a command window resulted in # a syntax error being thrown regarding the option. So # another approach was tried, namely using the write() method # of the file object. This had the same problem in the IDLE IDE # but ran correctly when run from the command prompt. # # However, the output included a blank line at the end of the # file. This was expected since it was surmized previously that # the newline character is maintained with the with the line # string that is read from the file. # # Two of the ways to extract what we want from the line are to # either use array indices to grab the first 16 characters, # which we are assuming are actually present, or to strip off # any newline characters from the right end of the string. To # use the first approach, we would use since the # indiced for a range start with the first element to be # included and end with the first element to not be included. # But the better way is to use the string method to # remove all newline characters, if there are any, from the # right end of the string. # # A somewhat trickier task is to output a newline character only # between actual lines. We can neither blindly put out a newline # before each line or after each line, since we want to put out # one fewer newlines than there are lines. One approach is to put # out a newline before each line except the first line. A fairly # common way to implement this is to initialize a 'firstline' to # 'True' and then check it on every pass through the loop before # we write out the line. If it is True, we set it to False and # don't put out the newline. If it is False, we do put out the # newline. Instead of using a simple flag, we can also use a # counter and check to see if the counter is still equal to its # initial value. Looking ahead, since we know we need to output # instruction addresses that are equal to the line number minus # one, this is an obvious way to kill two birds with one stone. #============================================================ # PROGRAMMER:........ William L. Bahn # USERID:............ WBAHN # COURSE:............ CSCI-410 # TERM............... FALL 2013 # ASIGNMENT:......... PY01 # FILENAME:.......... py01_3.py # PYTHON VERSION:.... 3.3.0 #============================================================ #============================================================ # Instructor's PARTIAL Solution # # This series of files (py01_?.py) represents the steps I # went through as I implemented this program. You'll notice a # strong dose of incrementalism (a.k.a., baby steps). #============================================================ # The final step is to format each line properly, which # entails adding the EOL comment delimiters followed by a # space, outputing the address as a five-digit zero padded # integer starting with 0 followed by a colon and space, and # finally parsing and outputting the instruction fields based # on the type of instruction. All but the last of these are # independent of the instruction type and so we will do those # first. Then we will tackle the instruction parsing. # # Outputing the the line leader (everything but the instruciton # itself) can be done with a single write using a formatted # output string with the appropriate format to produce a five # digit zero-padded integer when printing the . # # For the purposes of parsing, at least for now, we will assume # that the line really does consist of a 16-bit binary string. # We can check the first character and decide what type of # instruction we have. Then we can just brute force the parsing # from there. We could check the first character by treating # the line as an array, but it is better to use the string # methods where possible. In this case, there is a # method that does exactly what we need. # # To check that this was working, I simply output either "A-type" # or "C-type" depending on whether the instruction started with # a '0' or a '1', respectively. # # The next step was to parse the A-type instruction, since it is # the easier of the two. Again, we could use array indexing, but # it is worth spending some time looking for a suitable string # method. It appears that there IS not suitable method, so we # will use the array indices (which may well have been why no # string method to do the same thing was written). # # With all of the experimentation done to get the A-type # instructions parsed, modifying the single write() statement # to parse the C-type instruction is trivial. # # There is no doubt that the approach taken here is a bit like # using a hammer, but sometimes a hammer is a reasonable tool # to use. # # At this point the program is technically complete, but it # would be nice to at least take an initial shot at doing some # exception handling. #============================================================ # PROGRAMMER:........ William L. Bahn # USERID:............ WBAHN # COURSE:............ CSCI-410 # TERM............... FALL 2013 # ASIGNMENT:......... PY01 # FILENAME:.......... py01_4.py # PYTHON VERSION:.... 3.3.0 #============================================================ #============================================================ # Instructor's PARTIAL Solution # # This series of files (py01_?.py) represents the steps I # went through as I implemented this program. You'll notice a # strong dose of incrementalism (a.k.a., baby steps). #============================================================ # Now that the program is working, it is time to make it a # bit more robust. In most traditional programming languages, # the key to robustness is to check for conditions that will # cause problems and take action before the problem arises. # You can think of this approach as asking for permission # before doing something. In Python, the approach es to # assume that everything will work fine and to recover when # something goes wrong. This can be thought of as asking for # forgiveness. # # How you do this is through exception handling. You try # something and if it throws an exception, you catch the # exception and respond in a manner appropriate to the type # of exception that was thrown. This last part has a subtlety # that is easy to overlook (and we will overlook it here). # A given operation may throw an exception for a number of # reasons and the action that should be taken may be very # different for each one. Therefore, the best practice is # to only handle exceptions for specific types and leave # all others as "unhandled exceptions" and let the system # die. For our purposes, we will generally want to simply # issue an error message and quit the program, so it is not # unreasonable to lump all exceptions together. # The two most likely places where we might encounter problems # is when opening the two files. Thus we put the # call in a block followed immediately by an # block that contains the exception handling code. For us # we end the exception code with a call in order to # exit the program. #============================================================ # PROGRAMMER:........ William L. Bahn # USERID:............ WBAHN # COURSE:............ CSCI-410 # TERM............... FALL 2013 # ASIGNMENT:......... PY01 # FILENAME:.......... py01.py # PYTHON VERSION:.... 3.3.0 #============================================================ #============================================================ # Instructor's Solution #============================================================ # 1) Open input file "machine.hack" # 2) Open output file "machine.asm" # 3) Initialize address to 0 # 4) FOR each line in the input file # 4.1) Read in the line # 4.2) IF line is NOT the first line # 4.2.1) Output newline to output file # 4.3) Output line leader to output file # 4.3.1) Output EOL comment delimiter followed by space # 4.3.2) Output address (5-digit, zero padded) # 4.3.3) Output colon delimiter followed by space # 4.4) IF instruction is A-type # 4.4.1) Output instruction in 4-bit space-delimited groups # 4.5) ELSE # 4.5.1) Output instruction in {1,2,1,6,3,3}-bit groups # 4.6) Increment address # 5) Close output file # 6) Close input file