Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loop variable in BEGIN block becomes a VMNull #2379

Closed
Leont opened this issue Oct 16, 2018 · 11 comments
Closed

Loop variable in BEGIN block becomes a VMNull #2379

Leont opened this issue Oct 16, 2018 · 11 comments
Labels
phasers severe A problem that is encountered frequently, or a problem that needs attention for other reasons

Comments

@Leont
Copy link
Contributor

Leont commented Oct 16, 2018

The Problem

This code:

unit class Foo;

BEGIN {
    my $foo = 1;
    { $?CLASS.^add_method('foo', anon method () { dd $foo } ) }
} 

when run as

perl6 -I. -Mfoo -e'Foo.new.foo'

fails with

Cannot invoke this object (REPR: Null; VMNull)
  in sub  at /home/leont/Code/6pan/TestCase/lib/Foo.pm6 (Foo) line 4
  in method <anon> at /home/leont/Code/6pan/TestCase/lib/Foo.pm6 (Foo) line 5
  in block <unit> at -e line 1

unless one adds no precomplication to the class.

Environment

This is Rakudo version 2018.09 built on MoarVM version 2018.09

@Leont Leont changed the title Closure in loop in BEGIN block becomes a VMNull Loop variable in BEGIN block becomes a VMNull Oct 16, 2018
@AlexDaniel
Copy link
Contributor

FWIW this is not a recent regression: https://gist.github.com/1d7ab9005e3c53fae9b91c5fcfdbe1f2

@Leont Leont changed the title Loop variable in BEGIN block becomes a VMNull Variable in BEGIN block becomes a VMNull Oct 16, 2018
@Leont Leont changed the title Variable in BEGIN block becomes a VMNull Loop variable in BEGIN block becomes a VMNull Oct 16, 2018
@Leont
Copy link
Contributor Author

Leont commented Oct 16, 2018

Some more investigation indicates it's not the loop per se that's essential in triggering this, but it needs a scope below the main BEGIN one

@zoffixznet
Copy link
Contributor

zoffixznet commented Oct 16, 2018

but it needs a scope below the main BEGIN one

Doesn't look like even that is necessary. Just a core routine call inside the added method:

# Foo.pm6
unit class Foo;
BEGIN { $?CLASS.^add_method: 'foo', { join } }

# script.p6
use lib '.';
use Foo;
Foo.foo;

# OUTPUT: Cannot invoke this object (REPR: Null; VMNull)

And it happens only for core routine calls, not ones you define inside BEGIN.

And if you define a routine outside the begin and try to use it, you get a different error:

# Foo.pm6
unit class Foo;
sub join {}
BEGIN { $?CLASS.^add_method: 'foo', { join } }

# script.p6
use lib '.';
use Foo;
Foo.foo;

# OUTPUT: getlex: outer index out of range

@zoffixznet
Copy link
Contributor

Found what could possibly be a workaround you could use: assign a sub you want to use to another symbol inside BEGIN and then use that symbol inside the code of the method:

unit class Foo;
BEGIN { my &sym2 = &dd; $?CLASS.^add_method: 'foo', { sym2 42 } }

@Leont
Copy link
Contributor Author

Leont commented Oct 16, 2018

Found what could possibly be a workaround you could use: assign a sub you want to use to another symbol inside BEGIN and then use that symbol inside the code of the method:

That only work because &dd doesn't have to be kept alive. This for example will fail:

BEGIN { my &sym2 = sub ($arg) { dd $arg }; $?CLASS.^add_method: 'foo', { sym2 42 } }

@zoffixznet
Copy link
Contributor

Yeah, I guess it's fairly limited; you have to extract &dd into that scope as well:

unit class Foo;
BEGIN {
    my &dd2 = &dd; my &sym2 = sub ($arg) { dd2 $arg };
    $?CLASS.^add_method: 'foo', { sym2 42 } }

@niner
Copy link
Collaborator

niner commented Oct 17, 2018

This would probably be the place to start looking at: https://github.com/rakudo/rakudo/blob/master/src/Perl6/World.nqp#L2636
is_nested in that context means "BEGIN time EVAL"

@Leont
Copy link
Contributor Author

Leont commented Oct 17, 2018

Yeah, I guess it's fairly limited; you have to extract &dd into that scope as well:

That isn't going to help in my use-case, where I need to do this over many values.

@Leont
Copy link
Contributor Author

Leont commented Oct 29, 2018

This would probably be the place to start looking at: https://github.com/rakudo/rakudo/blob/master/src/Perl6/World.nqp#L2636
is_nested in that context means "BEGIN time EVAL"

That does indeed look like it deals with the outermost BEGIN scope and not further. Not that I'd know how to fix that.

@AlexDaniel AlexDaniel added the severe A problem that is encountered frequently, or a problem that needs attention for other reasons label Nov 18, 2018
@lizmat
Copy link
Contributor

lizmat commented Nov 18, 2018

FWIW, a similar issue exists with:

use nqp;
BEGIN my $h := nqp::hash("a",42);

@vrurg
Copy link
Member

vrurg commented Oct 29, 2019

Tested on 2019.07.1 – fails. HEAD passes.

Closing via MoarVM/MoarVM#1209 and 7e3d023

@vrurg vrurg closed this as completed Oct 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
phasers severe A problem that is encountered frequently, or a problem that needs attention for other reasons
Projects
None yet
Development

No branches or pull requests

7 participants