SMOP Lexical Scope Implementation


One first hard step in implementing lexical scopes is to put together a lot of details that are spread over the specs. In this page we're going to sketch a model for the lexical scopes that support all the documented Perl 6 features.

Variable Lookup

The local variable lookup happens in the following order:

  1. MY
  2. OUTER recursive

Special cases

$_

$_ is always locally defined in any block. Routines start with an empty $_, other Code objects have a signature of:

 -> $_ is rw = OUTER::<$_>

$! and $/

These variables are created empty in every new scope and marked as contextual, so their value can be set from the inner scopes and be seen from the caller. For instance, the regex code sets $+/ when the match succeeds, so that the calling code can see the match object.

Modelling

Data Structure

class LexicalScope {
  has %.entries handles postcircumfix:<{}>, exists;
  has LexicalScope $.outer is rw;
}

Accessing the Lexical Scope

The lexical scope is an attribute of the continuation, meaning that the "current continuation" points to the "current lexical scope". The Perl 6 specs doesn't specify a macro that return the current continuation, so we have one of the SMOP Specific Macros ___CURRENT_CONTINUATION___. This should provide access to the following API:

class Continuation {
  has LexicalScope $.lexical is rw;
  has Continuation $.outer_context is rw;
  has Continuation $.enclosing_routine is rw;
}

This should be part of the SMOP Interpreter Implementation API.

Making a variable lookup

class LexicalScope is also {
  method lookup($lexical: $name) {
    if ($lexical.exists($name)) {
      return $lexical{$name};
    } elsif ($lexical.outer) {
      return $lexical.outer.lookup($name);
    } else {
      fail("No variable $name in the current scope");
    }
  }
}