Compiling "Bobcat" Due 5/11 The "Bobcat" language is a scaled-down version of "Tiger" as defined in "Modern Compiler Implementation in Java". The only types are integers and strings (no records or arrays). Type checking is also not required to be enforced. Tiger expressions that are supposed to have no value (i.e, void), such as assignment operations, are assumed to carry 0 as their default value (so exactly one item is always left on the stack after the complete evaluation of each expression.) Functions in Bobcat all have global scope, as in C (no local function definitions). This implies that a function may not refer to variables that are not local, or passed in as parameters. No function can take more than six parameters (so we can use registers o0-o5 to pass them). Although functions can be of global scope, you must be able to compile nested let-expressions, respecting the scope of variables. To make up for the fact that our functions can't access non-local variables, we will add pointers to our language. Implement two special function calls: ref(x), and deref(x) which returns the address and contents of x respectively. For values (such as small constants) that do not have proper memory addresses, return 0. ref and defref correspond respectively to & and * in C, but introducing new operators symbols would mean changing the lexer and parser. Implementing these operations as special function calls is easier. Also implement a special function call: refassign(a,val) that assigns the value of val into a, interpreted as an address. You should be able to compile the following Tiger program. You will also be asked to demonstrate your compiler on source code I will provide later. let var x := 1 var y := 2 function g(x:int, y:string) : int = (print(y); x+5) function factorial(n:int) : int = /* you didn't really think ... */ if (n<2) then 1 else n*factorial(n-1) function swap(a:int, b:int) = let var temp := 0 in ( temp := deref(a); refassign(a, deref(b)); refassign(b, temp) ) end in ( let var x := x+1 /* watch out here! */ in x := x + 2 end; if (x=4) then print("it didn't work!") else if (x=1) then print("it worked!"); x := g(x,"hello") + 9000; /* large constant test */ swap(ref(x),ref(y)); if (y > 2) then print("referencing works!"); let var n := 5 in if (factorial(n)=120) then print("the factorial of 5 is indeed 120!") else print("something weird happened.") end ) end I've checked that the above program parsed. Of course, you may want to break it up into smaller chunks when testing.