Programming Languages problem, Procedural Language, Dynamic Scope

Viewed 226

I have been assigned such a problem in my software development course. So, the normal way is to check each procedure one by one and remember each call by each subprogram, however, I am a bit lazy programmer and I have decided to take a shortcut by implementing given pseudocode in an actual programming language.

Problem statement:

    procedure Main is
        X, Y, Z : Integer;
        procedure Sub1 is
            A, Y, Z : Integer;
        begin
        ...
        end;

        procedure Sub2 is
            A, B, Z : Integer;
        begin
        ...
            procedure Sub4 is
                A, B, W : Integer;
            begin
            ...
            end;
        end;

        procedure Sub3 is
            A, X, W : Integer;
        begin
        ...
        end;
    begin
    ...
    end;

Consider the program above. Given the following calling sequences and assuming that dynamic scoping is used, what variables are visible during the execution of the last subprogram activated? Include with each visible variable the name of the unit where it is declared (e.x. Main.X).

  • Main calls Sub1; Sub1 calls Sub3; Sub3 calls Sub2;

My Attempt:

$x = 10;
$y = 20;
$z = 30;
sub Sub2 
{ 
   return $x; 
}
sub Sub1
{ 
   local $x = 9; 
   local $y = 19; 
   local $z = 29; 
   return Sub2(); 
}
print Sub1()."\n";

I'm stuck at this point and have no idea how to change the code so that it shows me the variables. I see that solution is obvious, but I've coded in C++ and Java so far.

2 Answers

It would be nice if you've spent the time you used on asking this question on watching tutorials. However, we all have been there at one point, being confused exploring new languages. Try not to ask for the answer to your homework next time.

So, I see you'd like to use Perl, a good choice. I myself have done a similar task recently, here is my approach.

As R. Sebesta (2019) writes in the book named "Concepts of Programming Languages" (12 ed.), the best examples of dynamic scoping are Perl and Common Lisp.

Basically, it is based on the sequence of subprogram calls which are determined only at run time.

The following program shows how the subprogram calls affect variable value:

$x = 0;
$y = 0;
$z = 0;
sub sub1
{
    local $a = 1;
    local $y = 1;
    local $z = 1;
    return sub3();
}

sub sub2
{
    local $a = 2;
    local $b = 2;
    local $z = 2;
    sub sub4
    {
        local $a = 4;
        local $b = 4;
        local $w = 4;
    }
    return "Sub".$a.".A, "."Sub".$b.".B, "."Sub".$w.".W, "."Sub".$x.".X,
"."Sub".$y.".Y, "."Sub".$z.".Z";
    
}

sub sub3
{
    local $a = 3;
    local $x = 3;
    local $w = 3;
    return sub2();
}
print sub1()."\n";

Output: Sub2.A, Sub2.B, Sub3.W, Sub3.X, Sub1.Y, Sub2.Z
Note: Sub0 is just Main subprogram scope.

If you want to check the values of the variables in each subroutine you would dump them out with a module like Data::Dump or Data::Dumper.

sub foo { 
  printf "foo() current values are %s\n\n", 
    Data::Dumper::Dumper($a, $b, $c, $x, $y, $z);
}

If you want to see the call stack of the current subroutine you would use the Carp module.

use Carp;
sub foo { Carp::cluck("foo() here"); }
sub bar { foo() }

&bar;

# Output
foo() here at (eval 284) line 1.
        W::foo() called at (eval 284) line 1
        W::bar() called at (eval 285) line 1
        eval 'package W; bar' called at script.pl line 116
        console::_console called at script.pl line 473



Related