Thursday, November 12, 2015

Languages HW4

The format is a bit of a mess, but I just finished the second exam (which seemed to go fine; apparently studying does pay off) and am not really in the mood to work on cleaning it up.

CS4250: Programming Languages
HW42: Eric Buckley – 18148800
8.4) Requiring the use of unique closing reserved words (“fi” or “end-if” for “if”, etc.) for compound statements removes ambiguity around binding of subordinate clauses. For example, in C, the code:
if ( x == 0 )
      if ( y == 0 )
{
      y = 1;
      x = 1;
}
else
      y = 3;
relies on the programmer knowing that the else will bind to the closest open if. However, in Ruby, the statement would be written as:
if ( x = 0 ) then
      if ( y = 0 ) then
            y = 1
            x = 1
      else
            y = 3
      end
end
The ambiguity is resolved by the presence of the end keyword.
On the other hand, binding an else to the nearest open if is such a common paradigm that it can be argued that forcing the use of a closing keyword is superfluous at best and may even impede readability. Furthermore, the gains of using the closing keyword are only realized when a compound statement is used. Unless a language adopts the syntax (as does Ruby) that ALL blocks are compound statements, there will still be ambiguity when a single statement is used in the then clause. Forcing the use of compound block structures when a simple statement is used increases line count and decreases readability of otherwise straightforward structures.
8.9) Java’s restriction of using only Boolean statements in control structures was a response to the fact that many C and C++ program errors resulted from an inadvertent use of an arithmetic expression. In particular, “comparisons” of the form:
if ( x = 0 )
which will always evaluate to false as well as setting x to zero, when what was intended was
if ( x == 0 )
were so commonplace that experienced C programmers formed the habit of writing such expressions as
if ( 0 == x )
simply so the compiler would catch the error if the additional = sign was omitted.
                That said, there are legitimate reasons for the use of arithmetic expressions in control statements, the most common being the ubiquitous string copy that appears in nearly every C program ever written:
while (*dest++ = *src++);

This code is not only concise and well understood by any seasoned C programmer; most optimizing compilers will reduce it to a single assembly instruction (assuming the underlying hardware supports a string copy).
8.4Prog) The C program:
j = -3;
for (i = 0; i < 3; i++) {
      switch (j + 2) {
            case 3:
            case 2: j--; break;
            case 0: j += 2; break;
            default: j = 0;
      }
      if ( j > 0 ) break;
      j = 3 – i;
}
can be rewritten without goto’s or break as follows:
bool term = false;
j = -3;
for (i = 0; (i < 3) && !term; i++) {
      if ( 3 == (j+2) || 2 == (j+2) )
            j--;
      else if ( 0 == (j+2) )
            j += 2;
      else
            j = 0;

      if ( j > 0 )
            term = true;
      else
            j = 3 – i;
}
and even with that, if said programmer works for me, they’d better have their résumé up to date, because I’ll fire them.

9.5) Consider the program in C syntax:
void swap (int a, int b){
      int temp;
      temp = a;
      a = b;
      b = temp;
}
void main() {
      int value = 2, list[5] = {1, 3, 5, 7, 9};
      swap(value, list[0]);
      swap(list[0], list[1];
      swap(value, list[value]);

a)      The values of the variables after each call when pass by value is employed are:
value
list
note
2
{1, 3, 5, 7, 9}
values are switched in swap, but not returned to main
2
{1, 3, 5, 7, 9}

2
{1, 3, 5, 7, 9}


b)      When pass by reference is employed
value
list
note
1
{2, 3, 5, 7, 9}
swap switches and returns value and list[0]
1
{3, 2, 5, 7, 9}
swap switches and returns list[0] and list[1]
2
{3, 1, 5, 7, 9}
despite the aliasing on the call, once the addresses for value and list[value] (list[1] in this case) are passed, the subprogram does not modify the addresses, just the contents of those addresses. Therefore, swap will exchange the values of value and list[1].

c)       When pass by value-result is employed, the result depends on the time of address binding
value
list
note
1
{2, 3, 5, 7, 9}
swap switches and returns value and list[0]
1
{3, 2, 5, 7, 9}
swap switches and returns list[0] and list[1]
2
{3, 2, 2, 7, 9}
if address binding is done at the time of entry, the results are the same as call by reference. If however, address binding is done at the time of the exit AND addresses are computed left to right, then the return value for the second parameter (2) will be placed in list[value] which will evaluate to list[2], giving the result indicated to the left.

9.7) Consider the program in C syntax:
void fun (int first, int second) {
      first += first;
      second += second;
}
void main() {
      int list[2] = {1, 3};
      fun(list[0], list[1]);
}
a)      The resulting values of the list array when call by value is used is {1, 3} since the modified values are not returned to main.
b)      When call by reference is used, the content of each address is added to itself, yielding {2, 6}.
c)       When call by value-result is used, each value is added to itself and then returned to main, again yielding {2, 6}.

9.11) The out modifier in C# allows a value set in the called program to be returned to the calling program. This allows a method to return more than one intrinsic-typed value (objects and arrays are always passed by reference in C++, Java, and C#).  While Java and C++ can implement multiple return values, either by boxing (putting an intrinsic-typed element inside an object) or, in the case of C++ simply passing the reference, the out keyword offers a more reliable alternative. Out parameters MUST be set by the called program (similar to return values). Also, the referencing is somewhat safer in that the compiler will not allow aliasing of an address that may also be accessed through another reference, such as an element of an array or an object member. Finally, while the program will compile, a warning will be generated if an out parameter is used in an expression prior to having its value set.
10.9) Introducing a second static chain link which points to the grandparent activation instance decreases non-local access by at most 50%. In general, a depth difference of d would result in chains of length
since the grandparent chain can be followed back through any even depth differences, and then the parent chain used once for an odd difference. Thus
While this savings is not insignificant when d is large, it is offset by the fact that two chain pointers need to be maintained at program linkage, which increases the time for the call whether or not any non-local variables are ever used in the subprogram. Furthermore, an optimizing compiler should be able to predict how many non-local references are needed and determine if the chain should be computed once at entry or every time a variable is referenced. Thus, the savings is at best minimal and does not justify the additional complexity. (And really, if speed is a concern, the programmer shouldn’t be using such constructs to begin with).
10.11) If a static-chain process is used to implement blocks, the activation record must contain two of the five elements typically stored in the activation record:
·         The dynamic link, which points to the activation record of the enclosing block or subprogram. The block itself is considered to be one level deeper than its enclosing block/subprogram for purposes of resolving references to variables defined outside the block.
·         Space for variables defined inside the block
The other two elements are not necessary:
·         The static link is not necessary because it will always be the same as the dynamic link. (Blocks are always “called” from the block/subprogram that defines them.)
·         The return address is not needed because the block will not return control to the point where it was entered. Instead, control will flow out of the block either to the next statement following the block end or to the target of a goto.

·         Storage for parameters is also not needed because blocks do not take parameters.

No comments:

Post a Comment