/* grader_util.pure - some utilities used by grader.pure

Copyright (c) 2011-2012 by Peter Summerland <p.summerland@gmail.com>.

All rights reserved.

This software is is part of pure-stlvec, an addon to the Pure Programming
Language (http://code.google.com/p/pure-lang/).

This software is distributed under a BSD-style license 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 COPYING file
included with the pure-stlvec distribution package for details.

*/

using stlvec, stlstruct;

/*** filtered_files ***************************************************/

#! --nowarn
stl::defstruct ff_info
{
 file_pointer.pointer/readonly,
 filter_fun/readonly,
 eof_val/readonly,
 bfr,
 line_num.int
};
#! --warn

::filter (p,eof_val) fp = ff_info {fp,p,eof_val,0,-1};
::filter p fp = ::filter (p,-1) fp;

::fgets ffp::ff_info = res when
  fp = file_pointer ffp;
  next = bfr ffp;
  set_bfr ffp 0;
  res = if stringp next && (filter_fun ffp) next then 
          next 
        else if feof fp then
          set_line_num ffp (-1) $$
          eof_val ffp
        else 
          set_bfr ffp (fgets fp) $$ 
          set_line_num ffp (line_num ffp + 1) $$
          fgets ffp;
end; 

::feof ffp::ff_info = ~stringp (bfr ffp) when set_bfr ffp (fgets ffp) end;

// line number of last line returned by fgets, -1 after fgets returning
// eof_val or before any fgets. Must be called immediately after fgets
(::#) ffp::ff_info = line_num ffp;


/*** Parameter file parsing functions ***********************************/

// Return (ok, stlvec of parsed values) in the same order as the
// (key,parse_fun) pairs contained in key_funs
parse_parameter_file key_funs::list fp = err_count==0, sv when
  ss = split ";" $ strip_comments (fget fp);
  do parse_param ss;
  err_count, _ = foldl check_for_missing_param (0,0) sv;
end with 
  parse_param s = () when
    ris = reg_info $ regex "^\\s*(\\w*)\\s*=(.*)" REG_EXTENDED s 0; 
    key_str, param = if null ris then "", "" else ris!3, val (ris!5);
    ndx = stl::index_if (\(k,_)->k==key_str) key_funs;
    if ndx >= 0 then 
      replace sv ndx ((key_funs!ndx!kf_fun) param)
    else ();
  end;
  check_for_missing_param (err_count, ndx) param = 
    if sv!ndx === () then 
      fprintf stderr "bad or missing parameter parameter: %s\n" 
                     (key_funs!ndx!kf_key) $$
      (err_count+1, ndx+1)
    else (err_count, ndx+1);
  strip_comments s = s2 when
    s1 = regsub (\_->"\n") "/\\*+[^*]*\\*/"  REG_EXTENDED s 0;
    s2 = regsub (\_->"\n") "//[^\n]*\n" REG_EXTENDED s1 0;
  end;
end when
  sv = mkstlvec () (#key_funs);
  kf_key = 0;
  kf_fun = 1;
end;

// Parse and return a value of that satisfies p, else ()
parse_parameter p x = if p x then x else ();

// Parse and return a list of values that satisfy p, else ()
parse_parameter_list p xs = if rlistp xs && all p xs then xs else ();

// Parse and return a vector of values that satisfy p, else ()
parse_parameter_vector p v = if vectorp v && all p v then v else ();



