Cac::ObjectScript - Source Filter for embedding ObjectScript expressions in Perl


Cac documentation Contained in the Cac distribution.

Index


Code Index:

NAME

Top

Cac::ObjectScript - Source Filter for embedding ObjectScript expressions in Perl

SYNOPSIS

Top

 use Cac::ObjectScript;
 my $a = 1;
 $a = <? :a +1:>:
 <:K ^foobar(:a):>
 no Cac::ObjectScript; # disable source filter

DESCRIPTION

Top

This module allows you to embed ObjectScript expressions enclosed in "<?" ... ":>" or ObjectScript statements in "<:" ... ":>"

The expressions are not evaluated, they are compiled into ObjectScript functions for everlasting speed.

You can use bind variables using :var notation.

Generated routines are named CPERLxxxxxxxxxxxxxxxxxxxxxxxxx where each x stands for a hexadecimal digit.

This is currently the md5sum (except last 7 digits) over the version of this module and the expression.

Anyway this may change (do not rely on that :), but I gurarantee that I only generate routines named "CPERL*".

If you just want to evaluate a Cache-String (i.e: a non constant expression) use CacEval $string of the Cac package.

You could also the following instead:

 my $eval = "K GeorgeBush"; # this is a political statement :)
 <: @:eval:>

but it doesn't look so fine :) If you got this, you've probably understand that module.

If you insist to write order-loops, try something like this:

 my $a="";
 do {
      $a = <?$order(^rOBJ(:a)):>;
      print "$a\n";
    } while length $a;

EXPORTS

Top

 none.

BUGS

Top

 Design: This Module creates a routine for every <[:?] ...  :> expression.
         It should create a single routine for each Perl source file.
         (The current design "eats" routine-buffers)
         I'm going to change that but that's not too high on my priority list.
         (Finding a girlfriend is :)

SEE ALSO

Top

Cac, Cac::Global, Cac::Routine, Cac::Util, Cac::Bind.

AUTHOR

Top

 Stefan Traby <stefan@hello-penguin.com>
 http://hello-penguin.com


Cac documentation Contained in the Cac distribution.

package Cac::ObjectScript;

use 5.006;
use strict;
use warnings;
use bytes;
  
use XSLoader;
XSLoader::load Cac unless $Cac::xs_loaded++; # this is in cacperl.xs :)

require Exporter;
use AutoLoader qw(AUTOLOAD);

our @ISA = qw(Exporter);
our @EXPORT_OK = ( );
our @EXPORT = qw();
our $VERSION = 1.83;

use Filter::Simple ();
use Digest::MD5 "md5_hex";
use Cac::Global;
use Cac::Routine;
use Cac::Util;


# this is a political statement :)
sub michael_moore_for_president($$) {
   my ($expr,$type) = @_;
   my %bind;
   my @bind;
   my $md5 = md5_hex "$VERSION$expr"; # API may change, so we force recompile on version change
   my $rtn = substr "CPERL$md5", 0, 30;

   for(;;) {
      last unless $expr =~ m/\G[^:]*:([a-zA-Z][a-zA-Z0-9]*)/gx;
      push @bind, $1 unless $bind{$1}++;
   }
   
   unless(defined Gget "rOBJ", $rtn) {
      # ok, we need to generate COS this can be slow - make sure that at least we are fast :)
      my @lines;
      my $ni = $expr;
      my $code;
      $ni =~ s/\n/\\n/g;
      push @lines, "$rtn ; automagically generated by " . __PACKAGE__ . " $VERSION",
                   " ;      MD5: $md5",
                   " ;     Type: ".($type eq ":" ? "Statement" : "Expression"),
                   " ;    Input: \"$ni\"",
                   " Q";
      for my $i (0..$#bind) {
        $expr =~ s/\s*:$bind[$i]\s*/b$i/gx;
      }
      
      if($type eq '?') {
         # it's an expression
         $code = "Q ($expr)";
      } else {
         # it's a statement
         $code = "$expr  Q 0";
      }
      push @lines, "CODE(".join(",", map { "b$_" } (0..$#bind)).") $code";

      compileMAC($rtn, @lines);
   }
   return " +(&Cac::Routine::Call(".join(",", "'CODE'", "'$rtn'", map { "\$$_" } @bind)."))".($type eq ':' ? ";" : "");
}



Filter::Simple::FILTER sub { 
                              $_ =~ s/<([?:])\s*(.*?)\s*:>/michael_moore_for_president $2, $1/ge;
                           };


1;
__END__