Anarres-Mud-Driver
view release on metacpan or search on metacpan
lib/Driver/Compiler/Check.pm view on Meta::CPAN
# These are choice targets.
(map { $_ => 'NOCHECK' } qw(
MapAdd MapSub
)),
ObjEq => [ T_OBJECT, T_OBJECT, T_BOOL ],
ObjNe => [ T_OBJECT, T_OBJECT, T_BOOL ],
# These actually have custom choose routines.
(map { $_ => 'CHOOSE' } qw(
Index Range
)),
StrIndex => [ T_STRING, T_INTEGER, undef, T_INTEGER ],
StrRange => [ T_STRING, T_INTEGER, T_INTEGER, undef, undef,
T_INTEGER ],
# These are choice targets with nonstatic types
(map { $_ => 'NOCHECK' } qw(
ArrIndex ArrRange
MapIndex
)),
# These have nonstatic types
(map { $_ => 'CODE' } qw(
Member New
)),
Catch => [ T_UNKNOWN, T_STRING ],
Assign => 'CODE', # Output type is input type
ExpCond => 'CODE', # Output type is unification of input
Block => 'CODE', # Iterate over statements
StmtExp => [ T_UNKNOWN, T_VOID ],
StmtRlimits => [ T_INTEGER, T_INTEGER, 'BLOCK', T_VOID ],
StmtTry => 'CODE',
StmtCatch => [ 'BLOCK', T_VOID ],
# XXX These have to set up break and continue targets.
StmtDo => [ T_BOOL, 'BLOCK', T_VOID ],
StmtWhile => [ T_BOOL, 'BLOCK', T_VOID ],
StmtFor => [ T_VOID, T_BOOL, T_VOID, 'BLOCK', T_VOID ],
(map { $_ => 'CODE' } qw(
StmtForeach StmtForeachArr StmtForeachMap
)),
# StmtBreak also needs code to get the label.
# Most of the flow control statements probably need code.
StmtSwitch => 'CODE', # Open a new switch context
StmtCase => 'CODE', # Generate a label
StmtDefault => 'CODE', # Sort out the labels
StmtIf => 'CODE', # Handle the 'else' clause!
StmtBreak => 'CODE', # Get the break target
StmtContinue=> 'CODE', # Get the continue target
StmtReturn => 'CODE', # Output type must match function
Sscanf => 'CODE', # Urgh!
);
# This looks like a fast way of generating the choice table for
# promotable operators, but does depend a little on the naming
# of opcodes! If there are any special cases, they need to be put
# into %OPCHOICES as literals. I'm going to get lynched for this.
{
%OPCHOICES = ();
no strict qw(refs);
my $package = __PACKAGE__;
$package =~ s/[^:]+$/Node/;
foreach my $op (keys %OPTYPES) {
next unless $OPTYPES{$op} eq 'CHOOSE';
foreach my $tp (qw(Int Str Obj Arr Map)) {
push(@{ $OPCHOICES{$op} }, "$tp$op") if $OPTYPES{"$tp$op"};
}
}
}
# We can't do this because we then don't pass the new opcode type
# in the case that we're calling the superclass method! Furthermore,
# the subclass method we actually try to call won't exist.
# my $sub = \&{ "$package\::$tp$op::convert" }
# or die "No 'convert' in package $package\::$tp$op";
# A lot of superclass methods. These are found in ::Check via @ISA.
sub lvaluep { undef; }
sub constp { undef; }
sub assert { # This sucks somewhat
my ($self, $type) = @_;
if (!$self->type->equals(T_UNKNOWN)) { # DEBUGGING
confess "Asserting something of known type.";
}
print "Asserting " . $self->opcode . " into " . ${$type} . "\n";
return new Anarres::Mud::Driver::Compiler::Node::IntAssert($self)
if $type->equals(T_INTEGER);
return new Anarres::Mud::Driver::Compiler::Node::StrAssert($self)
if $type->equals(T_STRING);
return new Anarres::Mud::Driver::Compiler::Node::ArrAssert($self)
if $type->is_array;
return new Anarres::Mud::Driver::Compiler::Node::MapAssert($self)
if $type->is_mapping;
return new Anarres::Mud::Driver::Compiler::Node::ClsAssert($self)
if $type->equals(T_CLOSURE);
return new Anarres::Mud::Driver::Compiler::Node::ObjAssert($self)
if $type->equals(T_OBJECT);
confess "Cannot assert node into type " . $$type . "!\n";
return undef;
}
sub promote_to_block {
my ($self, $stmt) = @_;
return $stmt if ref($stmt) =~ /::Block$/;
confess "Can only promote statements into blocks, not " .
$stmt->opcode
unless ref($stmt) =~ /::Stmt[^:]+$/;
# It's a statement. This code is partially duplicated below.
return new Anarres::Mud::Driver::Compiler::Node::Block(
[], # locals
( run in 1.933 second using v1.01-cache-2.11-cpan-6aa56a78535 )