# Copyright (c) 1997-2007
# Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
# http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any
# later version: http://www.gnu.org/licenses/gpl.txt.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#----------------------------------------------------------------------------
# $Project: polymake $$Id: Shell.pm 7550 2007-01-10 12:25:54Z gawrilow $
use strict;
use namespaces;
use Poly::Application;
use Poly::User;
use Poly::File;
use Poly::Object;
use Poly::Pipe;
package Poly::Shell;
use Poly::Ext;
### FIXME: to be filled with interactive stuff
sub new {
bless [ ];
}
sub run {
die "interactive mode not implemented yet\n";
redefine Help("Poly::InteractiveHelp");
}
# the following three routines should access customizable variables from Poly::User package
sub load_apps {
eval {
package Poly::User;
if ((my ($app_name)=@_)>0) {
if (!defined($_[0]) || $_[0] eq "none") {
$application=_new Application(shift);
} else {
application($app_name);
}
} else {
foreach $app_name (@start_applications) {
add Application($app_name);
}
application($default_application);
}
};
if ($@) {
err_print($@);
exit 1;
}
}
sub run_script {
my ($scriptfile)=@_;
$scriptfile =~ s/^(\w+)::(?!$)//;
load_apps($1);
package Poly::User;
local @INC=($application, @INC, new Poly::Shell::BadScriptHandler);
local_unshift($application->myINC, ".", @lookup_scripts, $application->top."/scripts", "$main::InstallTop/scripts");
local_array($application->compile_preamble, [ "use strict; use namespaces;\n" ]);
local *default::=get_pkg(__PACKAGE__);
do $scriptfile;
beautify_error() if $@;
}
sub eval_expr {
package Poly::User;
local_unshift(\@INC, $application);
local_unshift($application->myINC, ".", @lookup_scripts, $application->top."/scripts", "$main::InstallTop/scripts");
local_array($application->compile_preamble, [ "use strict; use namespaces;\n" ]);
eval shift;
beautify_error() if $@;
}
# the line is considered as to be continued if it ends with:
# - an opening bracket whatever kind: { ( [
# - a binary operator: + - * / . cmp eq ...
# - a colon or a semicolon
sub is_continued {
$_[0] =~ m'(?: [{([.,;*/<>=] | (?<!\+)\+ | (?<!-)- | \b (?: cmp | le | lt | ge | gt | eq | ne | x)) \s*$ 'x;
}
sub run_pipe {
my ($pipe)=@_;
my ($cmd, $line, $apps_loaded);
while (length($cmd=<$pipe>)) {
while (is_continued($cmd) && length($line=<$pipe>)) {
$cmd.=$line;
}
if (!$apps_loaded) {
if ($cmd !~ /^\s* application (?:\s+|\()['"]\w+/xs) {
load_apps;
}
$apps_loaded=1;
}
local $main::scope=new Scope();
eval_expr($cmd);
if ($@) {
err_print($@);
} else {
$main::scope->perform_deferred;
}
}
$@='';
}
###############################################################################################
my @request;
package Poly::Shell::Dummy;
my $dummy=bless [ ];
sub AUTOLOAD { $dummy }
package Poly::User::Prepare;
sub AUTOLOAD {
$AUTOLOAD =~ /([^:]+)$/;
if (@_) {
die "unknown method or property: $1\n";
}
push @request, $1;
$dummy;
}
sub the_rest {
wantarray ? () : $dummy;
}
sub prepare {
no strict 'refs';
while (my ($func, $attr)=each %{$application->EXPORT}) {
*$func= is_code($attr)
? \&the_rest :
$attr eq "prop"
? \&$func : \&the_rest;
}
@request=();
}
###############################################################################################
package Poly::Shell;
sub compat_mode {
my $file=shift;
if (-f $file) {
# old style syntax: FILE PROPERTY ...
Poly::User::load($file);
if ($Switches::verify) {
$Poly::User::this->verify(@_);
return;
}
do {
package Poly::User::Prepare;
prepare();
my $i=1;
foreach (@_) {
if (/^ $id_only_re /ox and defined (my $label=$application->prefs->find_label($1))) {
if ($i<=$#_) {
if ($application->EXPORT->{$1} eq "user") {
warn_print( <<"." );
$1 is interpreted as prefer_now "$1";
but this is probably not exactly the same as you have meant.
The recommended way to enforce using $1 is to call it explicitly:
$1($_[$i])
.
}
$label->set_temp_preferred($main::scope);
} else {
warn_print( <<"." );
$1 is a label controlling the choice of functions following it
on the command line. Being put on the last position it does not
affect anything.
.
}
undef $_;
} else {
eval $_;
if ($@) {
$@ =~ s/^Bareword "([^"]+)" not allowed .*$/Unknown method, property, or label: $1/mg unless $Switches::d;
die beautify_error();
}
}
++$i;
}
};
if ($Switches::n) {
if (defined (my $schedule=$Poly::User::this->give_schedule(@request))) {
print $schedule->report, "\n";
} else {
err_print( "no suitable rules found\n" );
}
return;
}
$Poly::User::this->give(@request);
foreach my $expr (@_) {
next unless defined $expr;
my @pr=do {
package Poly::User;
no strict 'vars';
eval "printable($expr)"
};
die beautify_error() if $@;
if (@pr) {
enforce_nl($pr[-1]);
print "$expr\n", @pr, "\n";
}
}
} elsif ($file =~ /^ $id_only_re/xo) {
# slight variation of the old style: FUNCTION FILE ...
my $files_seen=0;
foreach my $arg (@_) {
if (-f $arg) {
$arg=Poly::User::load($arg);
++$files_seen;
}
}
load_apps if !$files_seen;
if (my $function=Poly::User->can($file)) {
if ($Switches::n) {
die "can't call function $file in dry run mode\n";
}
if (my @pr=Poly::User::printable($function->(@_))) {
enforce_nl($pr[-1]);
print "$file\n", @pr, "\n";
}
} else {
die "unknown function or file name: $file\n";
}
} else {
die "file $file does not exist\n";
}
}
###############################################################################################
# make this function visible for all modules and applications
sub Modules::returnObject {
my $obj=shift;
$obj->commit;
# try to guess the destination user variable
if (defined (my $name=return_to_var())) {
$obj->name ||= $name;
}
defined(wantarray) ? $obj : ($Poly::User::this=$obj);
}
package Poly::Shell::BadScriptHandler;
my $dummy=bless [ ];
sub new { $dummy; }
sub Poly::Shell::BadScriptHandler::INC {
$@="script file '" . pop(@_) . "' not found\n";
undef;
}
1
syntax highlighted by Code2HTML, v. 0.9.1