#! /usr/bin/perl -w
#feedseq <code> [<test-point file>]
#
# The inputs (one/line) in the file are fed to the given
#   code in sequence.  There is no initialization, so to reset
#   the .state file must be first removed.  Output is a sequence
#   of (value, state, runtime) triples.  The FIFO file mechanism is not used,
#   so an actual state file is used.
# If the test-point file isn't given, take input from keyboard until terminated.
#
# Also works on stateless code.
#
# If <code> has extension .ccfc then 'executes' a table-lookup approximation.

use component;

$code = shift;
$tests = shift;
if (defined($tests)) { #file name given
  die "must give code and test-point files." unless (defined($code) && defined($tests) && -e $code && -e $tests);
  open(T,"<$tests");
  chomp($in = <T>);  #use first input to initialize if necessary
  close T;
  $isfile = 1;
} else {
  die "must give code file." unless (defined($code) && -e $code);
  $isfile = 0;
  $in = 0;  #most likely legal input
}
@baseline = split('\.',$code);
$base = $baseline[0];
$ext = $baseline[1];
$tablelook = 0; 
$xqt = $code;
if (defined($ext)) { #extension given, check for "theory" file
  # only ".ccfc" is acceptable
  if ($ext eq "ccfc" || $ext eq "ccft") { #comp meas approx file (exists from above)
    $tablelook = 1;
  } elsif ($ext eq "ccf") {
    die "To execute table-lookup use $base.ccf[tc]";
  }
}
$statefile = $base.".state";
#print "State file name is: $statefile\n";  #debug
  if ($tablelook) { #not real code
    open(NC,"<$code");
    $head = <NC>;  #header line from approx file
    @heads = split(' ',$head); 
    if (not defined($heads[3])) { #stateless
      $stateless = 1;
      $xqt = "perl XqtF $code";
    } else {
      $stateless = 0;
      chop($code);  #remove last "c"
      $xqt = "perl XqtS $code";
    }
  }
$initialize = 1;
if (-e $statefile) {
  warn "(Continuing with existing state; remove $statefile to reset)";
  $stateless = 0;
  open(S,"<$statefile");
  chomp($inst = <S>);
  close S;
  $initialize = 0;
} else { #no existing state, find out if stateless
  unlink(glob("*.state"));  #remove any and all other state files 
  if (not defined($stateless)) { #already done above for tables
    ($out,$run) = component::excomp($in,$xqt);
    if (-e $statefile) { #it made a statefile, leave it in existence
      $stateless = 0;
    } else {
      $stateless = 1;
    }
  }
}
if ($isfile) {
  open(T,"<$tests");
  $readplace = T;
} else {
  $readplace = STDIN;
  print "Supply inputs one/line:\n";
}
$no1 = 1;
while ($in = <$readplace>) { #each line is an input value
  chop($in);
  if ($no1) {
    $no1 = 0;
    if ($stateless) {
      print "Input	|	Output	Runtime\n";
    } else {
      print "Input		State	|	Output		State	Runtime\n";
    }
  }
  #run code using IPC
  ($out,$run) = component::excomp($in,$xqt);
#print "running |$xqt|, out: $out, run: $run \n";  #debug

  if ($stateless) {
    printf("%4.2f	|	%4.2f	%4.2f\n", $in,$out,$run);
  } else {
    open(S,"<$statefile");
    chomp($outst = <S>);
    close S;
    if ($initialize) {
      $initialize = 0;
      printf("%4.2f	(initialize)		%4.2f	%12.10f	%4.2f\n",$in,$out,$outst,$run);
    } else {
      printf("%4.2f	%12.10f		%4.2f	%12.10f	%4.2f\n",$in,$inst,$out,$outst,$run);
    }
    $inst = $outst;
  }
}
if ($isfile) {
  close T;
}
