Answered step by step
Verified Expert Solution
Question
1 Approved Answer
complete java code Introduction Calling functions is a tricky business. There are several steps to take to make sure that everything is handled correctly. Consider:
complete java code
Introduction Calling functions is a tricky business. There are several steps to take to make sure that everything is handled correctly. Consider: define add ( a,b : integer; var c:integer) c:=a+b Now consider some different ways that we could call this code. add 1,2,varc add a,2+3, var a And some things that shouldn't happen (and should be an error!): add 1,2,3 add 1,2,a add 2.37.4 var a Another "gotcha" to think about - what if we change the value of a variable that is not marked as var. What should happen? We could throw an error. That would require us to look at every assignment statement and judge if the assigned variable is changeable. But we would also have to look at every function call, to see if the passed variable is marked as var! For example: define changer(var a : integer) a:=a+1 add a,1, var a define changer (var a : integer) a:=a+1 add a,1, var a And what if I call changer with: changer z One approach to this is to forbid it. If you try to call a function without matching "var", it should fail. This is a legitimate way to handle this situation, but we are doing something else - something that will let us deal with constants, too. When a function is called (that is, we encounter a FunctionCallNode): 1) Locate the function definition; this could be a built-in (like read or write) or it could be userdefined. We have a hash map for this. 2) Make sure that the number of parameters matches OR that the function definition is variadic. 3) Make a new collection of values (InterpreterDataType): For every parameter in invocation: a. Evaluate the parameter (expression()) b. Make a new IDT with the same value. c. Put that new value in the new collection. 4) Now we call the function: If the FunctionNode is actually a FunctionNode, call InterpretFunction on it. If the FunctionNode is actually a built-in, call Execute() on it. In both cases, pass in the new collection of IDTs 5) Finally, we loop over that set of values - the called function might have changed some! a. For each value, if the called function is variadic or the called function is marked as VAR and the invocation is marked as VAR then b. Update the variable value with the values "passed back" from the function (that is, in the list). Semantic Analysis This is an additional step that is performed once parsing is complete. Semantic Analysis This is an additional step that is performed once parsing is complete. In this step, we analyze the AST. In this step, we have all the data of the complete AST so we can do things like ensure (for example) that all variables are declared. In Shank, this is not an issue, since all variables are at the function scope (and declared at the top), but think about Java where a member variable could be declared after it is used in a method. Create a new class called SemanticAnalysis. Add a method called "CheckAssignments". We will pass our ProgramNode to this method. For each function, we need to look at every assignment statement (remember that they could be in sub-blocks like inside an "if" hint - recursion). Consider the variable on the left side of the assignment as the "correct" type. Make sure that everything on the right side of the assignment is the same type. If it is not, throw an exception. Add as much information as you can to help the user debug this. Also remember that operands can be variables or constants. You may need to make several functions to implement this 1 did. Call this method from "main" before you call the interpreterStep by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started