Acme-Chef
view release on metacpan or search on metacpan
lib/Acme/Chef/Recipe.pm view on Meta::CPAN
dishes => $clone->{dishes},
);
my $sous_done = $sous_recipe->execute( $recipes );
$self->output( $sous_done->output() );
$self -> {bowls} -> [0]
-> put( $sous_done -> first_bowl() -> new() -> pour() );
} elsif ( $return =~ /^loop\.([^\.]+)\.([^\.]+)/ ) {
my $verb = $1;
my $ingr = $2;
push @loop_stack, $verb;
if ( not $self -> {ingredients} -> {$ingr} -> value() ) {
pop @loop_stack;
$exec_pos = $self -> {loops} -> {$verb} -> {end};
}
} elsif ( $return =~ /^endloop\.([^\.]+)/ ) {
my $verb = $1;
$exec_pos = $self -> {loops} -> {$verb} -> {start} - 1;
} elsif ( $return =~ /^break/ ) {
my $verb = pop @loop_stack;
$exec_pos = $self -> {loops} -> {$verb} -> {end};
}
$exec_pos++;
last if $exec_pos > $max_pos;
}
if ( $self->{serves} ) {
foreach my $serve ( 0..($self->{serves}-1) ) {
last if $serve > $#{$self->{dishes}};
my $string = $self->{dishes}->[$serve]->print();
$self->{output} .= $string;
}
}
return $self;
}
=item first_bowl
Returns the first bowl of the recipe.
=cut
sub first_bowl {
my $self = shift;
return $self->{bowls}->[0];
}
=item require_ingredient
First argument must be an ingredient object. Second may be a string indicating
the location of the requirement. Throws a fatal error if the ingredient is not
present.
=cut
sub require_ingredient {
my $self = shift;
my $ingredient = shift;
my $sub = shift;
(defined $ingredient and exists $self->{ingredients}{$ingredient})
or croak "Unknown ingredient '".(defined$ingredient?$ingredient:'<undefined>').
"' required for recipe '$self->{name}'".
(defined $sub?" in '$sub'":'').".";
return $self;
}
=item output
Mutator for the Recipe output.
=cut
sub output {
my $self = shift;
$self->{output} .= shift if @_;
return $self->{output};
}
=item require_bowl
First argument must be a number of bowls. Additional bowls are added to the
recipe if it currently has less than this number of bowls.
=cut
sub require_bowl {
my $self = shift;
my $no = shift;
return if @{$self->{bowls}} >= $no;
while (@{$self->{bowls}} < $no) {
push @{$self->{bowls}}, Acme::Chef::Container->new();
}
return $self;
}
=item require_dish
First argument must be a number of dishes. Additional dishes are added to the
recipe if it currently has less than this number of dishes.
=cut
sub require_dish {
my $self = shift;
my $no = shift;
return if @{$self->{dishes}} >= $no;
while (@{$self->{dishes}} < $no) {
push @{$self->{dishes}}, Acme::Chef::Container->new();
}
return $self;
}
=item recipe_name
Mutator for the recipe name.
=cut
sub recipe_name {
my $self = shift;
$self->{name} = shift if @_;
return $self->{name};
}
=item compile
Tries to compile the recipe. Returns 0 on error or if the recipe was
already compiled. Returns the compiled recipe if the compilation succeeded.
=cut
sub compile {
my $self = shift;
return 0 if $self->{compiled};
my @ingredients = split /\n/, $self->{ingredients};
shift @ingredients; # remove header line
@ingredients or croak "Failed compiling recipe. No ingredients specified.";
my %ingredients;
my $ingredient_no = 0;
foreach (@ingredients) {
$ingredient_no++;
my $value;
if (s/^[ ]*(\d+)[ ]//) {
$value = $1;
} else {
$value = undef;
}
my $measure_type = '';
foreach my $type ( keys %Acme::Chef::Ingredient::MeasureTypes ) {
if ( s/^\Q$type\E[ ]// ) {
$measure_type = $type;
last;
}
}
my $measure = '';
foreach my $meas ( keys %Acme::Chef::Ingredient::Measures ) {
next if $meas eq '';
if ( s/^\Q$meas\E[ ]// ) {
$measure = $meas;
last;
}
}
/[ ]*([\-\w][\- \w]*)[ ]*$/
or croak "Invalid ingredient specification (ingredient no. $ingredient_no, name).";
my $ingredient_name = $1;
my $ingredient = Acme::Chef::Ingredient->new(
name => $ingredient_name,
value => $value,
measure => $measure,
measure_type => $measure_type,
);
$ingredients{$ingredient_name} = $ingredient;
}
( run in 0.559 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )