Acme-Perl-VM
view release on metacpan or search on metacpan
lib/Acme/Perl/VM.pm view on Meta::CPAN
}
deb ' VOID' if( ($flags & OPf_WANT) == OPf_WANT_VOID );
deb ' SCALAR' if( ($flags & OPf_WANT) == OPf_WANT_SCALAR );
deb ' LIST' if( ($flags & OPf_WANT) == OPf_WANT_LIST );
deb ' KIDS' if $flags & OPf_KIDS;
deb ' PARENS' if $flags & OPf_PARENS;
deb ' REF' if $flags & OPf_REF;
deb ' MOD' if $flags & OPf_MOD;
deb ' STACKED' if $flags & OPf_STACKED;
deb ' SPECIAL' if $flags & OPf_SPECIAL;
deb "\n";
}
sub runops_debug{
_op_trace();
while(${ $PL_op = &{$PL_ppaddr[$PL_op->type]} }){
if(APVM_STACK){
dump_stack();
}
_op_trace();
}
if(APVM_STACK){
dump_stack();
}
return;
}
sub _deb_colored{
my($fmt, @args) = @_;
printf STDERR Term::ANSIColor::colored($fmt, $color), @args;
return;
}
sub _deb{
my($fmt, @args) = @_;
printf STDERR $fmt, @args;
return;
}
sub mess{ # util.c
my($fmt, @args) = @_;
my $msg = sprintf $fmt, @args;
return sprintf "[APVM] %s in %s at %s line %d.\n",
$msg, $PL_op->desc, $PL_curcop->file, $PL_curcop->line;
}
sub longmess{
my $msg = mess(@_);
my $cxix = $#PL_cxstack;
while( ($cxix = dopoptosub($cxix)) >= 0 ){
my $cx = $PL_cxstack[$cxix];
my $cop = $cx->oldcop;
my $args;
if($cx->argarray){
$args = sprintf '(%s)', join q{,},
map{ defined($_) ? qq{'$_'} : 'undef' }
@{ $cx->argarray->object_2svref };
}
else{
$args = '';
}
my $cvgv = $cx->cv->GV;
$msg .= sprintf qq{[APVM] %s%s called at %s line %d.\n},
gv_fullname($cvgv), $args,
$cop->file, $cop->line;
$cxix--;
}
return $msg;
}
sub apvm_warn{
#warn APVM_DEBUG ? longmess(@_) : mess(@_);
print STDERR longmess(@_);
}
sub apvm_die{
# not yet implemented completely
# cf.
# die_where() in pp_ctl.c
# vdie() in util.c
die APVM_DEBUG ? longmess(@_) : mess(@_);
}
sub croak{
die APVM_DEBUG ? longmess(@_) : mess(@_);
}
sub PUSHMARK(){
push @PL_markstack, $#PL_stack;
return;
}
sub POPMARK(){
return pop @PL_markstack;
}
sub TOPMARK(){
return $PL_markstack[-1];
}
sub PUSH{
push @PL_stack, @_;
return;
}
sub mPUSH{
PUSH(map{ sv_2mortal($_) } @_);
return;
}
sub POP(){
return pop @PL_stack;
}
sub TOP(){
return $PL_stack[-1];
}
sub SET{
my($sv) = @_;
$PL_stack[-1] = $sv;
return;
}
sub SETval{
my($val) = @_;
$PL_stack[-1] = PAD_SV( $PL_op->targ )->setval($val);
return;
}
sub GET_TARGET{
return PAD_SV($PL_op->targ);
}
sub GET_TARGETSTACKED{
return $PL_op->flags & OPf_STACKED ? POP : PAD_SV($PL_op->targ);
}
sub GET_ATARGET{
return $PL_op->flags & OPf_STACKED ? $PL_stack[$#PL_stack-1] : PAD_SV($PL_op->targ);
}
sub MAXARG{
return $PL_op->private & 0x0F;
}
sub PUSHBLOCK{
my($type, %args) = @_;
$args{oldcop} = $PL_curcop;
$args{oldmarksp} = $#PL_markstack;
$args{oldscopesp} = $#PL_scopestack;
my $cx = "Acme::Perl::VM::Context::$type"->new(\%args);
push @PL_cxstack, $cx;
if(APVM_CX){
deb "%s" . "Entering %s\n", (q{>} x @PL_cxstack), $type;
}
return $cx;
}
sub POPBLOCK{
my $cx = pop @PL_cxstack;
$PL_curcop = $cx->oldcop;
$#PL_markstack = $cx->oldmarksp;
$#PL_scopestack = $cx->oldscopesp;
if(APVM_CX){
deb "%s" . "Leaving %s\n", (q{>} x (@PL_cxstack+1)), $cx->type;
}
lib/Acme/Perl/VM.pm view on Meta::CPAN
sub hv_store_ent{
my($hv, $key, $sv) = @_;
tie $hv->object_2svref->{ ${$key->object_2svref} },
'Acme::Perl::VM::Alias', $sv->object_2svref;
return;
}
sub hv_scalar{
my($hv) = @_;
my $sv = sv_newmortal();
$sv->setval(scalar %{ $hv->object_2svref });
return $sv;
}
sub defoutgv{
no strict 'refs';
return \*{ select() };
}
sub gv_fullname{
my($gv, $prefix) = @_;
$prefix = '' unless defined $prefix;
my $stashname = $gv->STASH->NAME;
if($stashname eq 'main'){
$prefix .= $gv->SAFENAME;
}
else{
$prefix .= join q{::}, $stashname, $gv->SAFENAME;
}
return $prefix;
}
# Utilities
sub sv_defined{
my($sv) = @_;
return $sv && ${$sv} && defined(${ $sv->object_2svref });
}
sub is_not_null{
my($sv) = @_;
return ${$sv};
}
sub is_null{
my($sv) = @_;
return !${$sv};
}
my %not_a_scalar;
@not_a_scalar{qw(AV HV CV IO)} = ();
sub is_scalar{
my($sv) = @_;
return !exists $not_a_scalar{ $sv->class };
}
sub mark_list{
my($mark) = @_;
return map{ ${ $_->object_2svref } } splice @PL_stack, $mark+1;
}
our %external;
sub apvm_extern{
foreach my $arg(@_){
if(ref $arg){
if(ref($arg) ne 'CODE'){
Carp::croak('Not a CODE reference for apvm_extern()');
}
$external{refaddr $arg} = 1;
}
else{
my $stash = do{ no strict 'refs'; \%{$arg .'::'} };
while(my $name = each %{$stash}){
my $code_ref = do{ no strict 'refs'; *{$arg . '::' . $name}{CODE} };
if(defined $code_ref){
$external{refaddr $code_ref} = 1;
}
}
}
}
return;
}
sub cv_external{
my($cv) = @_;
return $cv->XSUB || $external{ ${$cv} };
}
sub ddx{
require Data::Dumper;
my $ddx = Data::Dumper->new(@_);
$ddx->Indent(1);
$ddx->Terse(TRUE);
$ddx->Quotekeys(FALSE);
$ddx->Useqq(TRUE);
return $ddx if defined wantarray;
my $name = ( split '::', (caller 2)[3] )[-1];
print STDERR $name, ': ', $ddx->Dump(), "\n";
return;
}
sub dump_object{
ddx([[ map{ $_ ? $_->object_2svref : $_ } @_ ]]);
}
sub dump_value{
ddx([\@_]);
}
sub dump_stack{
require Data::Dumper;
no warnings 'once';
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Terse = TRUE;
local $Data::Dumper::Quotekeys = FALSE;
local $Data::Dumper::Useqq = TRUE;
deb "(%s)\n", join q{,}, map{
# find variable name
my $varname = '';
my $class = $_->class;
if($class eq 'SPECIAL'){
($varname = $_->special_name) =~ s/^\&PL_//;
$varname;
}
elsif($class eq 'CV'){
$varname = '&' . gv_fullname($_->GV);
}
else{
for(my $padix = 0; $padix < @PL_curpad; $padix++){
my $padname;
if(${ $PL_curpad[$padix] } == ${ $_ }){
$padname = $PL_comppad_name->ARRAYelt($padix);
}
elsif($_->ROK && ${$PL_curpad[$padix]} == ${ $_->RV }){
$padname = $PL_comppad_name->ARRAYelt($padix);
$varname .= '\\';
}
if($padname){
if($padname->POK){
$varname .= $padname->PVX . ' ';
}
last;
}
}
$varname . Data::Dumper->Dump([is_scalar($_) ? ${$_->object_2svref} : $_->object_2svref], [$_->ROK ? 'SV' : '*SV']);
}
} @PL_stack;
return;
}
sub _dump_stack{
my $warn;
my $ddx = ddx([[map{
if(ref $_){
is_scalar($_) ? ${$_->object_2svref} : $_->object_2svref;
}
else{
$warn++;
$_;
}
} @PL_stack]], ['*PL_stack']);
$ddx->Indent(0);
deb " %s\n", $ddx->Dump();
if($warn){
apvm_die 'No sv found (%d)', $warn;
}
return;
}
sub dump_si{
my %stack_info = (
stack => \@PL_stack,
markstack => \@PL_markstack,
cxstack => \@PL_cxstack,
scopstack => \@PL_scopestack,
savestack => \@PL_savestack,
tmps => \@PL_tmps,
);
ddx([\%stack_info]);
}
sub not_implemented{
if(!@_){
if($PL_op && is_not_null($PL_op)){
@_ = ($PL_op->name);
}
else{
@_ = (caller 0)[3];
}
}
push @_, ' is not implemented';
goto &Carp::confess;
}
sub call_sv{ # perl.h
my($sv, $flags) = @_;
if($flags & G_DISCARD){
ENTER;
SAVETMPS;
}
my $cv = $sv->toCV();
my $old_op = $PL_op;
my $old_cop = $PL_curcop;
$PL_op = Acme::Perl::VM::OP_CallSV->new(
cv => $cv,
( run in 2.786 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )