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

Bizarre "Cannot invoke this object (REPR: Null; VMNull)" error when invoking values of a Map constant #2809

Closed
Kaiepi opened this issue Apr 3, 2019 · 3 comments

Comments

Projects
None yet
1 participant
@Kaiepi
Copy link
Contributor

commented Apr 3, 2019

The Problem

I have no clue how to golf this and I can't push the code for this to my repo for people to reproduce with this until tomorrow, so I hope my explanation is sufficient.

In a chat bot I'm writing, I have a command that looks like this in a module called PSBot::Commands:

our $eightball = PSBot::Command.new:
    :name<8ball>,
    :default-rank<+>,
    method (Str $target, PSBot::User $user, PSBot::Room $room,
            PSBot::StateManager $state, PSBot::Connection $connection --> Result) {
        my Str $res = do given 20.rand.floor {
            when 0  { 'It is certain.'             }
            when 1  { 'It is decidedly so.'        }
            when 2  { 'Without a doubt.'           }
            when 3  { 'Yes - definitely.'          }
            when 4  { 'You may rely on it.'        }
            when 5  { 'As I see it, yes.'          }
            when 6  { 'Most likely.'               }
            when 7  { 'Outlook good.'              }
            when 8  { 'Yes.'                       }
            when 9  { 'Signs point to yes.'        }
            when 10 { 'Reply hazy, try again.'     }
            when 11 { 'Ask again later.'           }
            when 12 { 'Better not tell you now.'   }
            when 13 { 'Cannot predict now.'        }
            when 14 { 'Concentrate and ask again.' }
            when 15 { "Don't count on it."         }
            when 16 { 'My reply is no.'            }
            when 17 { 'My sources say no.'         }
            when 18 { 'Outlook not so good.'       }
            when 19 { 'Very doubtful.'             }
        }
        self.send: $res, $user, $room, $connection;
    };

PSBot::Command is a class that assigns the method given to &.command and invokes it on CALL-ME, among other things.

When the bot receives a message from the messages supply in a Cro::WebSocket::Client::Connection instance, it emits it to a supplier whose supply uses Supply.schedule-on, which is handled by a react/whenever block and passed to the parser. The parser splits the message received into individual lines, and for each line, calls $*SCHEDULER.cue with a block that passes the message data to the appropriate parser method if parsing the type of message received is supported. The chat and PM parser methods invoke the command if one is found in the message.

Anyway, the problem is attempting to run this command crashes the bot when the result of 20.rand.floor matches a when in the given block. This didn't happen before I refactored commands to use the PSBot::Command class instead of just being a routine, and doesn't happen with any other command.

Expected Behavior

$res should be assigned to the string in the when block matched.

Actual Behavior

The bot crashes with Cannot invoke this object (REPR: Null; VMNull).

Steps to Reproduce

This is not reproducable by others until I push my commits to my repo tomorrow. I'll explain how to reproduce it then. In the meantime, this is the full exception message:

Cannot invoke this object (REPR: Null; VMNull)
  in block  at /home/morfent/Documents/p6-PSBot/lib/PSBot/Commands.pm6 (PSBot::Commands) line 219
  in code  at /home/morfent/Documents/p6-PSBot/lib/PSBot/Commands.pm6 (PSBot::Commands) line 200
  in method <anon> at /home/morfent/Documents/p6-PSBot/lib/PSBot/Commands.pm6 (PSBot::Commands) line 200
  in method CALL-ME at /home/morfent/Documents/p6-PSBot/lib/PSBot/Command.pm6 (PSBot::Command) line 147
  in block  at /home/morfent/Documents/p6-PSBot/lib/PSBot/Parser.pm6 (PSBot::Parser) line 185
  in method parse-chat at /home/morfent/Documents/p6-PSBot/lib/PSBot/Parser.pm6 (PSBot::Parser) line 174
  in block  at /home/morfent/Documents/p6-PSBot/lib/PSBot/Parser.pm6 (PSBot::Parser) line 60
  in block  at SETTING::src/core/ThreadPoolScheduler.pm6 line 242
  in block  at SETTING::src/core/ThreadPoolScheduler.pm6 line 241
  in method run-one at SETTING::src/core/ThreadPoolScheduler.pm6 line 236
  in block  at SETTING::src/core/ThreadPoolScheduler.pm6 line 278

Environment

  • Operating system:
    OpenBSD bastille.kennel.qt 6.4 GENERIC.MP#683 amd64
  • Compiler version (perl6 -v):
    This is Rakudo version 2019.03 built on MoarVM version 2019.03
    implementing Perl 6.d.
@Kaiepi

This comment has been minimized.

Copy link
Contributor Author

commented Apr 3, 2019

This error also gets thrown when I attempt to put return q[$8ball is currently unavailable due to a bug in Perl 6's runtime.] at the beginning of the method. I think this may be related to strings in general, not the given/when block, or at least I would if this happened with any other command. I'm baffled

@Kaiepi

This comment has been minimized.

Copy link
Contributor Author

commented Apr 3, 2019

OK, it does happen with other commands. The issue seems to be with this line in PSBot::Parser:

my Map constant COMMANDS .= new: PSBot::Commands::.values.map(-> $command {
    ($command.name, $command)
});

The echo command, which just returns $target, works, but any other command throws.

I mitigated this for now by removing the COMMANDS constant, wrapping all of the command definitions in PSBot::Commands with BEGIN, changing them to use my instead of our, and throwing this at the end of the block:

for MY::.kv -> $name, $command {
    OUR::{$command.name} := $command if $command ~~ PSBot::Command;
}

This is a better way to write I was trying to do anyway since it doesn't store the commands twice in memory.

@Kaiepi Kaiepi changed the title Bizarre "Cannot invoke this object (REPR: Null; VMNull)" error when evaluating a when block in a given Bizarre "Cannot invoke this object (REPR: Null; VMNull)" error when invoking values of a Map constant Apr 3, 2019

@Kaiepi

This comment has been minimized.

Copy link
Contributor Author

commented Apr 14, 2019

I lost the code that this happened with since it was in the middle of a huge refactor and I neglected to make a commit where it happened. Closing since I can't golf this

@Kaiepi Kaiepi closed this Apr 14, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.