evalEmpire/method-signatures

Ability to replace Parse::Method::Signatures with Method::Signatures in TryCatch

Opened this issue · 0 comments

This is a use case for #64, the signature introspection API.

TryCatch takes an appalling 420ms just to load (by comparison Moose only takes 250ms) on my not at all slow laptop. TryCatch is a great module and this renders it useless to me.

Most of the cost is Parse::Method::Signatures which it uses to add types to its catch blocks. Pretty clever.

   Type checking of the exception can be performed by specifing a type
   constraint or where clauses in the signature as follows:

    catch (TypeFoo $e) { ... }
    catch (Dict[code => Int, message => Str] $err) { ... }

   As shown in the above example, complex Moose types can be used,
   including MooseX::Types style of type constraints

   In addition to type checking via Moose type constraints, you can also
   use where clauses to only match a certain sub-condition on an error.
   For example, assuming that "HTTPError" is a suitably defined TC:

    catch (HTTPError $e where { $_->code >= 400 && $_->code <= 499 } ) {
      return "4XX error";
    }
    catch (HTTPError $e) {
      return "other http code";
    }

Note it's the same syntax we have.

Here is the code in TryCatch which it uses to introspect the catch parameter just like a subroutine parameter would.

  my $sig = Parse::Method::Signatures->new(
    input => $proto,
    from_namespace => $self->get_curstash_name,
    type_constraint_callback => \&_string_to_tc,
  );
  my $errctx = $sig->ppi;
  my $param = $sig->param;

  $sig->error( $errctx, "Parameter expected")
    unless $param;

  my $left = $sig->remaining_input;

  my $var_code = '';

  if (my $var_name = $param->can('variable_name') ) {
    my $name = $param->$var_name();
    $var_code = "my $name = \$TryCatch::Error;";
  }

  # (TC $var)
  if ($param->has_type_constraints) {
    my $tc = $param->meta_type_constraint;
    $TryCatch::TC_LIBRARY->{"$tc"} = $tc;
    push @conditions, "TryCatch->check_tc('$tc')";
  }

  # ($var where { $_ } )
  if ($param->has_constraints) {
    foreach my $con (@{$param->constraints}) {
      $con =~ s/^{|}$//g;
      push @conditions, "do {local \$_ = \$TryCatch::Error; $con }";
    }
  }