Skip to content

Commit

Permalink
[dotnet] Add experimental support for :scope('outer') to PAST::Var (c…
Browse files Browse the repository at this point in the history
…urious to see how pmichaud++ reacts), which does a lexical lookup but skipping the current scope. Currently, bind not supported, and of course :isdecl is invalid.
  • Loading branch information
jnthn committed Oct 30, 2010
1 parent 2ad10c2 commit 0d78282
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
22 changes: 22 additions & 0 deletions dotnet/compiler/PAST2DNSTCompiler.pm
Expand Up @@ -832,6 +832,14 @@ our multi sub dnst_for(PAST::Var $var) {
return emit_lexical_lookup($var.name);
}
}
elsif $scope eq 'outer' {
if $var.isdecl {
pir::die("Cannot use isdecl when scope is 'outer'.");
}
else {
return emit_outer_lexical_lookup($var.name);
}
}
elsif $scope eq 'contextual' {
if $var.isdecl {
return declare_lexical($var);
Expand Down Expand Up @@ -1025,6 +1033,20 @@ sub emit_lexical_lookup($name) {
$lookup
}

# Emits a lookup of a lexical in a scope outside the present one.
sub emit_outer_lexical_lookup($name) {
if $*BIND_CONTEXT {
pir::die("Cannot bind to something using scope 'outer'.");
}
my $lookup := DNST::MethodCall.new(
:on('Ops'), :name('get_lex_skip_current'),
:type('RakudoObject'),
'TC',
DNST::Literal.new( :value($name), :escape(1) )
);
$lookup
}

# Emits a lookup of a dynamic var.
sub emit_dynamic_lookup($name) {
my $lookup := DNST::MethodCall.new(
Expand Down
24 changes: 22 additions & 2 deletions dotnet/runtime/Runtime/Ops.cs
Expand Up @@ -299,7 +299,7 @@ public static RakudoObject coerce_str_to_num(ThreadContext TC, RakudoObject Str,
/// <summary>
/// Gets a lexical variable of the given name.
/// </summary>
/// <param name="i"></param>
/// <param name="TC"></param>
/// <param name="name"></param>
/// <returns></returns>
public static RakudoObject get_lex(ThreadContext TC, string Name)
Expand All @@ -315,10 +315,30 @@ public static RakudoObject get_lex(ThreadContext TC, string Name)
throw new InvalidOperationException("No variable " + Name + " found in the lexical scope");
}

/// <summary>
/// Gets a lexical variable of the given name, but skips the current
/// scope.
/// </summary>
/// <param name="TC"></param>
/// <param name="name"></param>
/// <returns></returns>
public static RakudoObject get_lex_skip_current(ThreadContext TC, string Name)
{
var CurContext = TC.CurrentContext.Outer;
while (CurContext != null)
{
int Index;
if (CurContext.LexPad.SlotMapping.TryGetValue(Name, out Index))
return CurContext.LexPad.Storage[Index];
CurContext = CurContext.Outer;
}
throw new InvalidOperationException("No variable " + Name + " found in the lexical scope");
}

/// <summary>
/// Binds the given value to a lexical variable of the given name.
/// </summary>
/// <param name="i"></param>
/// <param name="TC"></param>
/// <param name="name"></param>
/// <returns></returns>
public static RakudoObject bind_lex(ThreadContext TC, string Name, RakudoObject Value)
Expand Down

0 comments on commit 0d78282

Please sign in to comment.