CS 331 Spring 2025  >  Exam Review Problems, Set E


CS 331 Spring 2025
Exam Review Problems, Set E

This is the fifth set of exam review problems.

Problems

Review problems are given below. Answers are in the Answers section of this document. Do not turn these in.

    1. In a Scheme expression, where can a dot (.) be placed?
    2. Rewrite the Scheme list (1 2 3), using dot wherever possible.
    3. Your instructor says, “Dot is not a procedure.” Explain the meaning of and motivation behind this statement.
  1. Draw the following Scheme expression as a binary tree.
    (() . 1) . 2)
    1. What is the standard Scheme numeric equality procedure?
    2. What is the standard Scheme numeric inequality procedure?
    3. How does your instructor recommend checking equality of non-numeric values in Scheme?
    1. What is a Scheme macro?
    2. What is a pattern-based macro?
    3. What is a hygienic macro?
    1. In the context of Scheme macros, what is a keyword?
    2. Give an example of a Scheme macro keyword.
    1. What do we mean by static semantics?
    2. Give an example of an issue that is covered by static semantics. Hint. You may need to specify which programming language you are talking about.
  2. In the C++ Standard, how is the semantics of C++ specified—entirely formally, entirely informally, or a combination of the two?
    1. What is a tree-walk interpreter?
    2. Tree-walk interpreters are not used very often. Why not?
    1. Some interpreters compile the given source code to a machine-language like form that is not intended to be human-readable. What is such a form called?
    2. A program that executes code in this form directly is usually called what?
    1. A JIT compiler compiles code while it runs. This would seem to be impossible. Explain, briefly, how a JIT actually workd.
    2. Though time-consuming to write, a well written JIT is generally the most desirable kind of interpreter. Why is this the case?
    1. One advantage of a JIT is that it can do profile-based optimizations. What are these?
    2. A JIT will typically rate code sections on a scale from cold to hot. What do these temperature ratings indicate?
  3. What do we mean by program state?
    1. How are variables typically stored at runtime in a programming language with static typing and scope?
    2. How are variables typically stored at runtime in a dynamic programming language?
  4. What do we call the code that aids in the execution of a program? For example, such code might include handling of program startup and shutdown, low-level memory management, and/or the implementations of complex programming-language operations.
  5. The programming language you implemented in three assignments has no fatal runtime errors. Explain how this design choice significantly impacted the semantics of this programming language.
    1. What is unification?
    2. Explain how to unify the two lists [X, 4] and [1, Y], where X and Y are free variables.
    1. Fill in the blank. In logic programming, we are not so much interested in whether something is true or false, as we are in whether it is ________.
    2. What ramifications does the above have for negation?
    3. Briefly, what is the primary strategry for proving something in Prolog?
    1. What is Prolog predicate?
    2. Fill in the blank. The name of a Prolog predicate is always a Prolog ________.
    1. True or false: In Prolog, lists and numeric expressions are both examples of compound terms.
    2. True or false: A Prolog program is made of facts, rules, and queries.
    1. What is a Prolog fact?
    2. What is a Prolog rule?
    3. Every Prolog fact or rule ends with what?
    4. Every Prolog rule contains another particular sequence of characters. What is this sequence?

Answers

    1. In Scheme, we can place a dot just before the last item in what would otherwise be a list with at least two items. For example, we can write “(1 2 3 . 4)
    2. The Scheme list (1 2 3) can also be written as (1 . (2 . (3 . ()))).
    3. Your instructor says, “Dot is not a procedure.” This is true because dot is not a procedure. It is important because it means that the arguments of dot are not evaluated as one would expect if it were a procedure. For example, “((car x) . (car y))” might be expected to construct a pair whose first item is the car of x and whose second item is the car of y. However, since dot is not a procedure, this is actually just another way of writing the three-item list “((car x) car y)”.
  1. Below is the Scheme value
    (() . 1) . 2)
    drawn as a binary tree.
    Image not displayed: Binary tree representation of Scheme value
    1. The standard Scheme numeric equality procedure is =.
    2. Scheme has no standard numeric inequality procedure.
    3. Your instructor recommends checking equality of non-numeric values in Scheme using procedure equal?.
    1. A Scheme macro is a specified code transformation that is known to the Scheme implementation.
    2. A pattern-based macro is a macro in which one or more patterns are given; code that matches a pattern is transformed as indicated.
    3. A hygienic macro is one that limits interaction between identifiers inside the macro and those outside—in much the same way that such interactions can be limited in procedures, using local variables.
    1. In the context of Scheme macros, a keyword is a word in a pattern that matches only itself.
    2. The else that can be used as the last condition in a Scheme cond construction is an example of a Scheme macro keyword.
    1. Static semantics refers to issues of meaning that are handled before a program runs.
    2. One issue that involves static semantics is determination and checking of types in a programming language that has static typing: C, C++, Java, Haskell, etc. Other answers are possible.
  2. In the C++ Standard, the semantics of C++ is specified entirely informally.
    1. A tree-walk interpreter is an interpreter that processes an AST and executes it directly, without creating any other intermediate representation.
    2. Tree-walk interpreters are not used very often because they have poor performance.
    1. This form of code is called a byte code.
    2. A program that executes byte code directly is usually called a virtual machine.
    1. A JIT compiler is given byte code. This is split into multiple sections, each of which is executed as appropriate by a virtual machine. Between these executions, one or more of the sections may be compiled to machine language. In the future, if such a section needs to be executed, it can simply be called like a function; the virtual machine is not necessary.
    2. Huh? What? Because it’s faster! (Did I get it right?)
    1. Profile-based optimizations are optimizations based on information about what portions of code spend the most time executing.
    2. Higher-temperature ratings indicate that fast execution is a higher priority for a code section. A hotter code section is more likely to be compiled, more likely to be aggressively optimized, and more likely to be re-compiled with more optimization.
  3. The state of a program includes all information about the current situtation of a running program. This includes all of the following.
    • The current execution location.
    • The values of all variables.
    • The call stack.
    1. In a programming language with static typing and scope, variables are typically laid out in memory—static space or the call stack. There is a location for each variable; its value is stored there.
    2. In a dynamic programming language, values of variables are typically stored in an associative structure, usually a hash table. The variable name is the key; the associated value is the variable’s value.
  4. The code that aids in the execution of a program is called the runtime system, or simply the runtime.
  5. Since our programming language has no fatal runtime errors, undefined variables and functions have a specified default value. And computations that would normally have no numeric value—for example, division by zero—have a specified numeric value.
    1. To unify two constructions is to make them the same by binding variables as necessary.
    2. We can unify [X, 4] and [1, Y] by setting X = 1 and Y = 4.
    1. In logic programming, we are not so much interested in whether something is true or false, as we are in whether it is provable.
    2. This emphasis on provability means that negation is about something not being provable—as opposed to not being true.
    3. The primary strategry for proving something in Prolog is to attempt to unify it with something known to be true.
    1. A Prolog predicate is something we might prove to be true.
    2. The name of a Prolog predicate is always a Prolog atom.
    1. True. In Prolog, lists and numeric expressions are both examples of compound terms.
    2. False. A Prolog program is made of facts and rules, but not queries.
    1. A Prolog fact says that something is true.
    2. A Prolog rule says that something is true if other things can be proven. It is a way of deriving new known things from other known things.
    3. Every Prolog fact or rule ends with a dot (.).
    4. Every Prolog rule contains the character sequence “:-”.