1 / 147

Unit 27 Interpreter

Unit 27 Interpreter. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 25 Interpreter. Summary prepared by Kirk Scott. The Introduction Before the Introduction. There are several problems with this chapter Among them are the following:

valora
Download Presentation

Unit 27 Interpreter

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Unit 27Interpreter Summary prepared by Kirk Scott

  2. Design Patterns in JavaChapter 25Interpreter Summary prepared by Kirk Scott

  3. The Introduction Before the Introduction • There are several problems with this chapter • Among them are the following: • 1. The book doesn’t explain the following two points very well: • A. What is an interpreter? • B. Why would you want to use the Interpreter design pattern? • The book touches on these questions in the last subsection of the chapter • Even then, the book seems to concede that not all of the machinery is present in order to make this be very practical or seem very practical

  4. 2. Another shortcoming is that in implementing the pattern, some of the book’s code is not easy to understand • This breaks down into two sub-problems • A. The underlying problem seems to me to be that the code violates encapsulation • Not only is this potentially a poor choice, but this is part of what makes it hard to understand

  5. B. The additional observation on this is that the book’s explanations are not incredibly transparent • The code is hard to understand, and even after reading the explanations, you’re left wondering whether the book’s approach was a good idea or not

  6. 1.A What is an Interpreter? • Returning to point 1 in more detail: • In general, in what problem domain do you expect to hear about interpreters? • The answer is, this belongs in the category of language processing • In other words, you think of interpreters and compilers at the same time • These are pieces of code which allow you to translate from a source language to a target language, from high level code to machine code

  7. If you have had a course in programming languages or compilers you might also have heard the terms lexical analyzer and parser • These terms refer to different steps in reading a source file containing statements in some language, and translating them, ultimately, into a sequence of instructions that can be executed on a computer chip

  8. For the sake of background, here is a definition of a lexical analyzer (from Aho, Sethi, and Ullman • “The lexical analyzer is the first phase of a compiler. Its main task is to read the input characters and produce as output a sequence of tokens that the parser uses for syntax analysis.” • In other words, given a stream of characters, break it into a sequence of constants, variables, operators, keywords, etc.

  9. Here is a definition of a parser (from Aho, Sethi, and Ullman) • “In our compiler model, the parser obtains a string of tokens from the lexical analyzer, …, and verifies that the string can be generated by the grammar for a source language. We expect the parser to report any syntax errors in an intelligible fashion.” • In other words, the parser checks to see whether the input, after having been broken into tokens, forms a set of statements in the supposed source language.

  10. The last stage in a compiler is translation from the verified statements of the source file to an equivalent sequence of instructions in the target language • So what’s an interpreter, compared to a compiler? • In very simple terms, an interpreter is a system that translates each statement as it’s parsed, and executes it without waiting to translate the complete program

  11. Interpretation can be a preferred way of dealing with programs for several reasons • It is common with command languages, for example • Users may enter ad hoc sequences of instructions at a command prompt • These instructions may be calls to external applications like system utilities

  12. If on the command side, it’s difficult to foresee and impossible to control exactly what results the system utility produces, then a compiler may not be able to form a complete program • It is better to have an interpreted system that is flexible and responsive to the results that are produced command by command • In other words, it makes sense to translate one step at a time

  13. You may recall that Java is referred to as an interpreted language • On the other hand, you are also familiar with the idea that you have to compile Java source code • What’s going on? • A Java source file is written in Java, a high level, human understandable language

  14. Compilation results in a class file, containing what is known as bytecode • Bytecode is not machine language for any actual physical machine • It is the language of the Java Virtual Machine • What is the Java Virtual Machine? • In one respect, it is a simulated machine which runs bytecode

  15. In another respect, it is an interpreter • It interprets bytecode, line by line, into code that can run on the physical host machine • What advantage is there to this overall design? • Java is “universal” • It can be run on any hardware for which a Java Virtual Machine exists

  16. The code is only compiled once, into bytecode • It is not compiled a second time, into machine language • When a Java class file is to be run, there is no delay while it is translated in its entirety into machine language code • It starts running immediately—running on the machine simulation—running “on” the interpreter which the Java Virtual Machine is

  17. B. Why Would You Want to Use the Interpreter Design Pattern? • The book tries to illustrate the Interpreter design pattern in a practical, applied way • Instead of worrying about the problems of language interpretation, the authors pose the problem of creating programs that interact with and control machines in a factory • They develop a mechanism that makes it possible to build programs that would have this effect

  18. Then at the end of the chapter they observe that you could write programs directly which would control the machines • It’s not clear that you’ve gained any benefit from the machinery that makes it possible to compose sequences of commands which could be used as machine control programs • In response to this, they observe the following:

  19. It would be possible to have another language, a language for controlling machines, in which a programmer/engineer/person responsible for a machine could write a program to control it • Such a language would not have to have the features of Java • It could be restricted to concepts of machine control only

  20. Writing machine control programs in such a language would be simpler • The problem would then become, how to translate them into Java code for use in factory environment where implementations were done in that language

  21. The book finally concludes that you would need a parser that could translate from the simple, machine control language, into the machinery for building Java programs which they present as the Interpreter design pattern • Then the interpreter design pattern as presented here would become useful

  22. On the one hand, we can be thankful that the book doesn’t try to complete the job by developing a parser • On the other hand, it turns out that the motivation for the Interpreter design pattern is incomplete • We are shown how it’s done, but it’s hard to imagine that it’s very useful when the book concedes that you could just write straight Java code to accomplish all that the examples accomplish

  23. In conclusion in this introductory subsection, I can only say this: • It’s an eternal problem that when you try to explain something complicated, you end up simplifying • The simplification often makes the example seem pointless • This doesn’t mean that the design pattern is useless • Regardless of the examples, the goal is to understand the pattern

  24. 2.A Encapsulation is Violated • It appears that the authors violate encapsulation in part of their implementation of the Interpreter design pattern • This will be pointed out specifically in the code when it is presented • The statement is always made that violating encapsulation is bad • At the very least, you will see that it makes the code hard to understand

  25. The book’s explanations don’t really make it clear • This may lead you to the following, valid conclusion: • Maybe part of the reason that violating encapsulation is bad is that it leads to code that is hard to understand • Maybe part of the reason for developing the concept of encapsulation was to try to avoid the difficulties in understanding that become evident when encapsulation is violated

  26. Introductory Book Material • The Interpreter design pattern can be used to make objects where the objects, in essence, are like individual commands • Different kinds of commands are implemented as different classes • Each of these classes has a method of the same name, something like execute(), and the difference in the command objects consists of the fact that the code for the execute() method differs among the different command classes

  27. In general, the Interpreter design pattern can be thought of as supporting multiple commands • Structurally, the Interpreter pattern is similar to the State and Strategy patterns because each class has the same method • Recall that in the State example, every door state had a touch method • In the strategy example, every kind of advisor had a recommend() method • With the interpreter, each kind of command will have an execute() method

  28. The Interpreter design pattern is also closely related to the Composite design pattern • The Interpreter pattern will be used to create sequences of commands • Macros or subroutine calls in a program are subsequences of commands • A complex sequence of commands may consist of single commands as well as composite commands • A reasonably complete implementation of the Interpreter pattern will track the way things can be put together as individual leaf items, and composite nodes, where each of these is a type of component

  29. Book definition: • The intent of the Interpreter pattern is to let you compose executable objects according to a set of composition rules that you define.

  30. An Interpreter Example • The book illustrates the Interpreter design pattern using the robots that transport material between machines and that can load and unload the machines • The UML diagram on the following overhead shows a Robot class and a small hierarchy of commands • The command hierarchy is the same in structure as a composite hierarchy

  31. In looking at the UML diagram, the following things should be noticed: • There is an abstract method, execute(), at the top of the command hierarchy • It is concretely implemented in the two subclasses • The CommandSequence class also has an add() method for building up composites • Otherwise, there are no other methods in the Command hierarchy

  32. Also notice that the CarryCommand class has a constructor, which takes two machines as input parameters • The way a command is set up to work on robots/machines is by constructing it with the necessary references • There are corresponding instance variables for these references in the CarryCommand class • You can foresee that the implementation of the execute() method will work by calling the carry() method of the Robot class on these references

  33. The next thing to ask is, “So, what part of this design is the interpreter?” • The answer is, the command hierarchy is in essence the interpreter • A program, named ShowInterpreter, will be given shortly, which illustrates the use of the hierarchy

  34. A bunch of things are assumed in the code, but they’re not difficult • You obtain a machine composite object for the factory in Dublin, Ireland • You then obtain references to specific machines • You then write code to load bins into the machines

  35. You then construct two instances of CarryCommand using these machines as input parameters • You then construct an instance of CommandSequence and add the individual commands • Finally, you call execute on the sequence object • It is this one, final line of code which controls the robot/machines in the factory

  36. In essence, the whole machine control program has been packaged up in the one object and the one call to the execute() method • This is what the mean by “composing sequences of instructions” • The code is given on the next overhead

  37. public class ShowInterpreter • { • public static void main(String[] args) • { • MachineCompositedublin = OozinozFactory.dublin(); • ShellAssembler assembler = (ShellAssembler) dublin.find("ShellAssembler:3302"); • StarPress press = (StarPress) dublin.find("StarPress:3404"); • Fuser fuser = (Fuser) dublin.find("Fuser:3102"); • assembler.load(new Bin(11011)); • press.load(new Bin(11015)); • CarryCommand carry1 = new CarryCommand(assembler, fuser); • CarryCommand carry2 = new CarryCommand(press, fuser); • CommandSequenceseq = new CommandSequence(); • seq.add(carry1); • seq.add(carry2); • seq.execute(); • } • }

  38. Rather than showing the code for the command classes in advance, the book shows it after the example where it is used • The CommandSequence class has an ArrayList of commands • The add() method allows commands to be added

  39. The execute() method looks like the methods, like isTree(), in the composite design pattern • It iterates over all of the elements of the ArrayList calling execute() on them • If the element is a leaf, then the version of execute() in the CarryCommand class is used • If the element is a composite, then the call is recursive • The code for the CommandSequence class is shown on the next overhead

  40. public class CommandSequence extends Command • { • protected List commands = new ArrayList(); • public void add(Command c) • { • commands.add(c); • } • public void execute() • { • for (inti = 0; i < commands.size(); i++) { • Command c = (Command) commands.get(i); • c.execute(); • } • } • }

  41. The CarryCommand class has references to two machines • It has a constructor that takes two machine references as input parameters • And it is has an execute() method • The execute() is implemented by making a call to carry() on the single instance of Robot maintained in the Robot class, passing the machine references as parameters to this method • The code is shown on the following overhead

  42. public class CarryCommand extends Command • { • protected Machine fromMachine; • protected Machine toMachine; • public CarryCommand(Machine fromMachine, Machine toMachine) • { • this.fromMachine = fromMachine; • this.toMachine = toMachine; • } • public void execute() • { • Robot.singleton.carry(fromMachine, toMachine); • } • }

  43. The next step in developing the Interpreter design pattern is to add more subclasses to the Command hierarchy • The idea is that each different command type, in its execute() method, will package up a different kind of action that could be taken in controlling machines in a factory • This expands and generalizes the kind of total program for machine control that the interpreter pattern can generate and package altogether

  44. In addition to a CarryCommand, there might be a StartUpCommand and a ShutDownCommand • In addition to simple commands, there might be commands that reflect the structure of a programming language • This is where the complexity starts to set in

  45. The tree-like structure of the composite makes it possible to simply model macros, namely subsequences of code • However, a complete programming language allows iteration • The book introduces the idea of a ForCommand into the Command hierarchy • The ForCommand class implements the logic of a for each loop • The UML diagram for the expanded interpreter is shown on the next overhead • Explanations follow

  46. Most of the UML diagram is just a generalization of the previous one—with more Command classes added • The new aspect of the diagram is the arrow from the ForCommand class to the Command class • An instance of ForCommand will have a reference to another command • This other command constitutes the body of the for each loop

  47. In general, you might expect a design pattern that starts to mimic the elements of a programming language to need a construct that is like a variable • The book points out that in particular, something that works like a for each loop depends on a variable

  48. The syntax for a simple for each loop was given in Unit 9 of CS 202 with this example: • for(Cup7 someCup: mycollection) • { • myterminal.println(someCup); • } • mycollection was an ArrayList, for example, and someCup was a variable local to the loop which referred to the successive elements of mycollection

More Related