Skip to content
Block Statements & Nesting
step 1/3

Reading — step 1 of 3

Blocks — Creating New Scopes

~2 min readStatements & State

Block Statements & Nesting

A block statement is a sequence of statements enclosed in curly braces { ... }. Blocks create new scopes and are the building blocks for control flow, functions, and classes.

Syntax

{
    var x = 1;
    var y = 2;
    print x + y;    // outputs: 3
}
// x and y are no longer accessible here

Parsing Blocks

blockStmt → "{" statement* "}"

When we see {, we enter a new block. We parse statements until we see }. Each block creates a new environment.

Nesting

Blocks can nest arbitrarily deep:

{
    var a = 1;
    {
        var b = 2;
        {
            var c = 3;
            print a + b + c;   // outputs: 6
        }
        // c is gone
    }
    // b is gone
}
// a is gone

Each level creates a new environment linked to its parent. Variable lookup walks outward through the chain. This is O(d) where d is the nesting depth — acceptable for an interpreter, but we will optimize this with a resolver later.

Executing Blocks

When executing a block:

  1. Create a new environment with the current environment as enclosing
  2. Execute each statement in the block using the new environment
  3. Discard the block's environment (restoring the previous one)
executeBlock(statements, environment):
    previous = currentEnvironment
    currentEnvironment = new Environment(enclosing=environment)
    for stmt in statements:
        execute(stmt)
    currentEnvironment = previous  // restore

The restore step is critical — it is what makes variables "disappear" when the block ends. In a language with exceptions, you need a finally block or RAII pattern to ensure the environment is always restored.

Shadowing

A variable in an inner scope can have the same name as one in an outer scope:

var x = "outer";
{
    var x = "inner";   // shadows outer x
    print x;           // inner
}
print x;               // outer (unchanged)

The inner declaration creates a new variable in the inner environment. It does not modify the outer one. Some languages (like Rust) actually encourage shadowing — let x = x.parse() is idiomatic.

Your Task

Implement block statements that create new scopes. Variables declared inside a block should not be accessible outside it. Nested blocks should correctly shadow variables.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…