Lecture 17, Blocks

Part of the notes for 22C:196:002 (CS:4908:0002)
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Blocks

The falcon grammar says (somewhat abridged):

<block> ::= { <statement> [ ";" ] } { <block element> }
<block element> ::= "code" { <statement> [ ";" ] }
                         |  [ "private" ] "var" { <variable declaration> [ ";" ] }
<variable declaration> ::= <identifier> [ ":" ] <type>

In short, a block is a sequence of statements mixed with declarations, and one type of declaration is a variable declaration.

Looking further, we find that blocks occur in several contexts. The first context is the body of a procedure (or function, but we're abridging the grammar here):

 ::=  [  ]
                            
 ::= "external" | (  "end" )

The second context is involves the construction of a record type (the Falcon term for what C and C++ call a struct, but also used for objects, because blocks may contain procedure and function declarations, which in this context become the methods of the object).

<type> ::= <reference>
        |  <enumeration>
        |  <subrange>
        |  <record>
<record> ::= "record" <block> "end"

The third context involves the bodies of certain types of statements:

<statement> ::= <if>
             |  <assignment>
<if> ::= "if" <expression> [ "then" ]
              <block>
       [ "else"
              <block> ]
         "end"

So what are the semantic attributes of a block?

Of course, there is the code associated with the various statements, but here, we are interested in the attributes associated with the declarations in the block.

Hierarchic Scope Rules

Essentially, each block establishes a set of name-attribute pairs as the environment in which each statement and declaration in that block is evaluated. When searching for the definition of a variable or other named item in a particular context, the immediately enclosing block is searched first, and then the block that encloses that one, and so on, until all enclosing blocks have been examined.

Falcon can be compiled by a one-pass compiler, so we add one more rule: The only declarations visible from any point in the code are those that occur textually before that point.

In the abstract, the above model suffices, but in the real world, it is useful to distinguish between two kinds of blocks:

Free Blocks
The blocks that are the bodies of procedures or functions and the blocks that are the bodies of records establish entirely new environments. While the hierarchic scope rules allow code within such a block to reference variables outside that block, the semantics of such references are complicated, as will be discussed in the next lecture.

Block Extensions
Blocks declared in the body of a statement extend the block enclosing that statement. In a sense, these behave like simple concatenation, but when the end of a block extension is reached, that extension is discarded. Nesting of such blocks is comparatively simple. In effect, each declaration extends the current block, but and when a block extension is discarded, the associated declarations are removed from the current block.