Dallycot
view release on metacpan or search on metacpan
lib/Dallycot/Context.pm view on Meta::CPAN
package Dallycot::Context;
our $AUTHORITY = 'cpan:JSMITH';
# ABSTRACT: Execution context with value mappings and namespaces
use strict;
use warnings;
use utf8;
use Moose;
use namespace::autoclean;
use Array::Utils qw(unique array_minus);
use Scalar::Util qw(blessed);
use MooseX::Types::Moose qw/ArrayRef/;
use Carp qw(croak cluck);
use experimental qw(switch);
use Promises qw(deferred);
#
# Contexts form a chain from the kernel on down
# The context for a statement has no parent, but is copied from the kernel's
# context. Changes made are copied back to the kernel context info.
# Closures need to copy all of the info into a new context that is marked as
# a closure.
has namespaces => ( is => 'ro', isa => 'HashRef', default => sub { +{} }, lazy => 1 );
has environment => ( is => 'ro', isa => 'HashRef', default => sub { +{} }, lazy => 1 );
has namespace_search_path => ( is => 'ro', isa => 'ArrayRef', default => sub { [] }, lazy => 1 );
has parent => ( is => 'ro', isa => 'Dallycot::Context', predicate => 'has_parent' );
has is_closure => ( is => 'ro', isa => 'Bool', default => 0 );
sub add_namespace {
my ( $self, $ns, $href ) = @_;
if ( ( $self->is_closure || $self->has_parent )
&& defined( $self->namespaces->{$ns} ) )
{
croak "Namespaces may not be defined multiple times in a sub-context or closure";
}
$self->namespaces->{$ns} = $href;
return;
}
sub get_namespace {
my ( $self, $ns ) = @_;
if ( exists( $self->namespaces->{$ns} ) ) {
return $self->namespaces->{$ns};
}
elsif ( $self->has_parent ) {
return $self->parent->get_namespace($ns);
}
}
sub has_namespace {
my ( $self, $prefix ) = @_;
return exists( $self->namespaces->{$prefix} )
|| $self->has_parent && $self->parent->has_namespace($prefix);
}
sub add_assignment {
my ( $self, $identifier, $expr ) = @_;
if ( ( $self->is_closure || $self->has_parent ) ) {
my $d = $self->environment->{$identifier};
if ( $d && $d->is_resolved ) {
croak "Identifiers may not be redefined in a sub-context or closure";
}
}
if ( defined $expr ) {
if ( $expr->can('resolve') ) {
return $self->environment->{$identifier} = $expr;
}
else {
my $d = deferred;
$d->resolve($expr);
return $self->environment->{$identifier} = $d;
}
}
else {
return $self->environment->{$identifier} = deferred;
}
}
( run in 0.556 second using v1.01-cache-2.11-cpan-39bf76dae61 )