The 24 hour window to obtain/return the exam is there to support students writing from time zones around the world, and to support those who experience technical difficulties accessing/submitting the exam. Given that, it should in no way interfere with your ability to complete your other scheduled exams (e.g. CSCI 310) in that 24-hour time window.
Question | Mark |
1. let over lambda and OO [10 marks] | |
2. macros in C++ and lisp [10 marks] | |
3. grammars, lex, and yacc [10 marks] | |
4. parameter handling [10 marks] | |
5. precedence and associativity [10 marks] | |
6. higher order functions [10 marks] | |
7. loops and branching [10 marks] | |
8. write your own exam question [10 marks] | |
Exam Total [80 marks] |
Question 1: let over lambda and OO [10]
Below we provide a C++ class and an approximate let-over-lambda equivalent.
class mytime { private: int hh, mm; public: mytime() { hh = 0; mm = 0; } bool set(int h, int m); int gethh() { return hh; } int getmm() { return mm; } }; bool mytime::set(int h, int m) { if ((h >= 0) && (h < 60) && (m >= 0) && (m < 60)) { hh = h; mm = m; return true; } else { return false; } } | (defun mytime () (let ((hh 0) (mm 0)) (labels ( ; local functions (set (h m) (if (and (>= h 0) (< h 60) (>= m 0) (< m 60)) (block 'oktime (setf hh h) (setf mm m) t))) (gethh () hh) (getmm () mm)) ; dispatcher (lambda (cmd &optional (arg1 0) (arg2 0)) (cond ((equalp cmd 'set) (set arg1 arg2)) ((equalp cmd 'gethh) (gethh)) ((equalp cmd 'getmm) (getmm)) (t (format t "bad command~%"))))))) |
Suppose we make the following changes/additions to the C++ class:
// change 1: adding optional parameters to the constructor mytime(int h = 0, int m = 0) { hh = 0; mm = 0; set(h, m); } // change 2: adding a print method void print() { cout << hh << ":" << mm << endl; } |
Provide equivalent changes/additions to the let-over-lambda.
Question 2: macros in C++ and lisp [10]
Macros in C++ are primarily based on the use of templates, whereas in lisp they are based on the defmacro.
Question 3: grammars, lex, and yacc [10]
Below we give lex and yacc files for the following grammar:
/* Supported grammar: * program --> stmtlist * stmtlist --> statement stmtlist * --> statement * statement --> assignment * assignment --> TOK_IDENT TOK_ASSIGN value TOK_SEMI * value --> intexpr * intexpr --> TOK_INT * */ |
Alpha [a-z] Digit [0-9] %{ #include |
%{ #include |
Provide the necessary changes/additions to the file to handle the following changes/additions to the grammar:
new token: TOK_INTTYPE is the keyword "INTEGER" new grammar rules: statement --> vardecl vardecl --> TOK_INTTYPE TOK_IDENT TOK_SEMI new behaviour: the program counts how many variable declarations are made, and prints this count in function yywrap |
Question 4: parameter handling [10]
Early implementations of C did not require a function prototype to specify return type or the number/types of parameters, e.g. the following was valid:
#include <stdio.h> f(); /* prototype for function f */ int main() { int x = 3; char y = 'q'; float z = f(x,y); printf("%g\n", z); } float f(a, b) /* spec for function f */ int a; /* spec for param a */ char b; /* spec for param b */ { /* body of f, eventually returning a float */ } |
This code can still be compiled and run, though the format is now regarded as obsolete. A header file containing a set of function definitions might thus look something like
#ifndef SOMENAME #define SOMENAME /* function prototypes */ foo(); blah(); anotherfoo(); #endif |
Discuss the problems this could cause for developers and for compiler-writers, particularly in dealing with cases where a program consisted of multiple .c files, all seperately compiled into .o files before linking.
Question 5: precedence and associativity [10]
Suppose you were helping develop a new scripting language, and were given the opportunity to select both the associativity and precedence rules for a set of string operators:
(i) What levels/order of precedence would you choose for the operators and why?
(ii) Which of those operator(s) would you have evaluated left-to-right, and which would you have evaluated right-to-left, and why?
Question 6: higher order functions [10]
(i) Some of the pointer issues a C++ programmer has to deal with are dangling pointers, wild pointers, null pointers, and memory leaks. Of those four categories of pointer problem, which one(s) are relevant in the context of function pointers and why?
(ii) Suppose we wish to create a C function that operates (to a limited degree) like the lisp map function. It would take three parameters: a pointer to a function that takes an int as a parameter and returns an int, an array of ints, an int specifying the size of the array.
The map function would allocate an array of ints (the same size as the array passed), apply the passed function to each element of the array parameter, storing the result in the allocated array. When done, the map function would return the address of the allocated array, for example:
int square(int x) { return x * x; } int main() { int arr[3] = { 1, 2, 10 }; int *result = map(square, arr, 3); // the array result points to should now contain 1, 4, 100 } |
Provide an implementation of the map function.
Question 7: loops and branching [10]
(i) Argue both for and against the following statement:
(ii) If you were implementing a simplified form of the C language, and could only include one type of loop, which would it be and why?
Question 8: Write your own exam question [10]
Provide a new exam question and sample solution that would be an good addition to this CSCI 330 final exam, along with a justification of why you think it would have been a good question to include in the exam.
The criteria are as follows: