use Imager::Regops;
use strict;
+use vars qw($VERSION);
+
+$VERSION = "1.005";
my %expr_types;
$expr_types{$name} = $pack;
}
+sub type_registered {
+ my ($class, $name) = @_;
+
+ $expr_types{$name};
+}
+
sub _variables {
return @{$_[0]->{variables}};
}
sub compile {
my ($self, $expr, $opts) = @_;
+ $expr =~ s/#.*//; # remove comments
my @st_ops = split ' ', $expr;
for (@st_ops) {
{
$return = $item[1];
for my $op(@{$item[2]}) { $return = [ $op->[0], $return, $op->[1] ] }
+ 1;
}
relstuff : relop addition { $return = [ @item[1,2] ] }
$return = $item[1];
# for my $op(@{$item[2]}) { $return .= " @{$op}[1,0]"; }
for my $op(@{$item[2]}) { $return = [ $op->[0], $return, $op->[1] ] }
+ 1;
}
addstuff : addop multiply { $return = [ @item[1,2] ] }
addop : '+' { $return = 'add' }
{ $return = $item[1];
# for my $op(@{$item[2]}) { $return .= " @{$op}[1,0]"; }
for my $op(@{$item[2]}) { $return = [ $op->[0], $return, $op->[1] ] }
+ 1;
}
mulstuff : mulop power { $return = [ @item[1,2] ] }
{
$return = $item[2];
for my $op(reverse @{$item[1]}) { $return = [ @{$op}[1,0], $return ] }
+ 1;
}
| atom
powstuff : atom powop { $return = [ @item[1,2] ] }
# generate the final result
my $result = $self->gencode($optree->[1]);
if ($result !~ /^p\d+$/) {
- $self->error("You must return a colour value");
+ $self->error("You must return a color value");
return;
}
push(@{$self->{genops}}, [ 'ret', $result, (0) x $MaxOperands ])
You will need to set an expression value and you may set any of the
following:
-=over 4
+=over
-=item constants
+=item *
+
+constants
A hashref defining extra constants for expression parsing. The names
of the constants must be valid identifiers (/[^\W\d]\w*/) and the
Imager::Expr may define it's own constants (currently just pi.)
-=item variables
+=item *
+
+variables
A reference to an array of variable names. These are allocated
numeric registers starting from register zero.
=back
-By default you can define a 'rpnexpr' key (which emulates RPN) or
-'expr' (an infix expression). It's also possible to write other
+=for stopwords RPN
+
+By default you can define a C<rpnexpr> key (which emulates RPN) or
+C<expr> (an infix expression). It's also possible to write other
expression parsers that will use other keys. Only one expression key
should be defined.
Imager::Expr provides only a few simple methods meant for external use:
-=over 4
+=for stopwords VM
+
+=over
+
+=item Imager::Expr->type_registered($keyword)
+
+Returns true if the given expression type is available. The parameter
+is the key supplied to the new() method.
+
+ if (Imager::Expr->type_registered('expr')) {
+ # use infix expressions
+ }
=item $expr->code()
=item $expr->cregs()
-Returns a reference to the array of colour registers.
+Returns a reference to the array of color registers.
=item $expr->dumpops()
=item $expr->dumpcode()
-Returns a string with the unassembled VM "machine code".
+Returns a string with the disassembled VM "machine code".
=back
Methods used by parsers:
-=over 4
+=over
+
+=item compile
+
+This is the main method you'll need to implement in a parser. See the
+existing parsers for a guide.
+
+It's supplied the following parameters:
+
+=over
+
+=item *
+
+$expr - the expression to be parsed
+
+=item *
+
+$options - the options hash supplied to transform2.
+
+=back
+
+Return an array ref of array refs containing opcodes and operands.
=item @vars = $self->_variables()
Converts marginally parsed RPN to register code.
+=item assemble()
+
+Called to convert op codes into byte code.
+
+=item numre()
+
+Returns a regular expression that matches floating point numbers.
+
+=item optimize()
+
+Optimizes the assembly code, including attempting common subexpression
+elimination and strength reducing division by a constant into
+multiplication by a constant.
+
+=item register_type()
+
+Called by a new expression parser implementation to register itself,
+call as:
+
+ YourClassName->register_type('type code');
+
+where type code is the parameter that will accept the expression.
+
=back
=head2 Future compatibility