Ilya Zakharevich on Fri, 10 Mar 2006 04:41:03 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PATCH 2.2.11+] Support for packages: require()


On Tue, Jan 31, 2006 at 09:19:06PM -0800, Ilya Zakharevich wrote:
> > This is the second part of "package" support in GP/PARI (installing
> > functionality via loaded library written in GP).  This patch enables
> > new gp function require() documented in the first chunk.
> 
> Actually, one needs also support for versioning and export from the
> module namespace.  Since a couple of things needed to be changed, the
> following patch REPLACES the original patch.

Attached is the first "package", string.gp, which implements (and
exports by default) functions

  substring index rindex split

acting over the string type.  It should go into a place where PARI can
find it (see ?require).  I think it should be included by default.  I
also attach a test script for this package.

It would be great also if the example scripts shipped with GP/PARI are
repacked as packages.

Enjoy,
Ilya
string::EXPORT = ["substring", "index", "rindex", "split"];
string::VERSION = [1,0,0];

\\ len>0, l is length(str) + 1, off and len are 1-based and checked
string::_::substring(string::_str,string::_off,string::_len,string::_l) =
{
  string::_len = string::_off + string::_len - 1; \\ pos of the last char
  if(string::_len >= string::_l, string::_len = string::_l - 1);
  concat(vecextract(Vec(string::_str),Str(string::_off ".." string::_len)))
}

string::substring(string::_str,string::_off,string::_len="end") =
{
  local(string::_l);
\\  string::_str = Str(string::_str);
  string::_l = length(string::_str) + 1;
  if(string::_off<=0,   string::_off += string::_l);
  if(string::_off<=0 || string::_off > string::_l,
     error("string::substring(): substring outside of string"));
  if(string::_len=="end", string::_len = string::_l - string::_off);
  if(string::_len<0,      string::_len += string::_l - string::_off);
  if(string::_len<0,      error("string::substring(): End before start"));
  if(string::_len==0,     return(""));		\\ vecextract() misbehaving
  string::_::substring(string::_str,string::_off,string::_len,string::_l);
}

string::_::index(string::_dir,string::_str,string::_substr,string::_pos) =
{
  local(string::_l, string::_L, string::_e);
\\  string::_str = Str(string::_str);
  string::_L = length(string::_str);
\\  string::_substr = Str(string::_substr);
  string::_l = length(string::_substr);
  if(string::_pos=="edge", string::_pos = if(string::_dir>0, 1, string::_L + 1));
  if(string::_pos <= 0,    string::_pos += string::_L);
  if(string::_pos <= 0 || string::_pos > string::_L + 1,
     error("string::_::index(): position outside of string"));
  if(string::_substr == "", return(string::_pos));
  if(string::_dir > 0,
     string::_e = string::_L - string::_l + 2;
      if(string::_e <= string::_pos, return("")),
     if(string::_pos > string::_L - string::_l + 1,
	string::_pos = string::_L - string::_l + 1);
      string::_e = 0;
      if(string::_e >= string::_pos, return(""))
  );
  while(string::_e != string::_pos,
	  if(string::_substr
 == string::_::substring(string::_str,string::_pos,string::_l,string::_L+1),
		return(string::_pos));
	  string::_pos += string::_dir);
  return("");
}

string::index(string::_str,string::_substr,string::_pos="edge") =
  string::_::index( 1,string::_str,string::_substr,string::_pos)

string::rindex(string::_str,string::_substr,string::_pos="edge") =
  string::_::index(-1,string::_str,string::_substr,string::_pos)

string::split(string::_str,string::_substr) =
{
  local(string::_l, string::_L, string::_e, string::_pos, string::_p);
\\  string::_str = Str(string::_str);
\\  string::_substr = Str(string::_substr);
  if(string::_substr=="", return(Vec(string::_str)));
  string::_L = length(string::_str);
  string::_l = length(string::_substr);
  string::_e = 1 - string::_l;		\\ Start
  string::_pos = vector(string::_L + 1);
  string::_pos[1] = string::_e;
  string::_p = 1;			\\ found+1
  while(string::_e != "",
	string::_e = string::index(string::_str, string::_substr, string::_e + string::_l);
	string::_pos[string::_p++] = string::_e);
  string::_pos[string::_p] = string::_L + 1;
  vector(string::_p - 1, string::_,
	 string::substring(string::_str,
			   string::_pos[string::_] + string::_l,
			   string::_pos[string::_ + 1] - string::_pos[string::_] - string::_l))
}

{
  addhelp(string::substring,
	  "string::substring(STR,OFF,{LEN}): returns substring of STR"
	 " starting at position POS and of length LEN.  Position of the"
	 " beginning of string is 1; non-positive values of position count"
	 " from the end of string. Negative values of LEN are positions"
	 " relative to the end of string; the default value of LEN is to"
	 " the end of the string.");
  addhelp(string::index,
	  "string::index(STR,SUBSTR,{POS}): returns position of the first"
	 " substring SUBSTR of STR at or after position POS; position 1"
	 " is the beginning of string (this is the default for POS)."
	 " Non-positive POS is a position relative to"
	 " the end of string. Returns \"\" on failure.");
  addhelp(string::rindex,
	  "string::rindex(STR,SUBSTR,{POS}): returns position of the last"
	 " substring SUBSTR of STR at or before position POS; position 1"
	 " is the beginning of string. POS defaults to end-of-string."
	 " Non-positive POS is a position relative to"
	 " the end of string. Returns \"\" on failure.");
  addhelp(string::split,
	  "string::split(STR,SEPARATOR): break STR into pieces by cutting"
	 " out substrings equal to SEPARATOR. Returns a vector with pieces.");
}

1;
counter=0;
test(f)=counter++; if(!f,print1("not ")); print("ok "counter)

require(string);
test(substring("abcd",2,0)=="");
test(substring("abcd",2,1)=="b");
test(substring("abcd",2,2)=="bc");
test(substring("abcd",2,3)=="bcd");
test(substring("abcd",2,4)=="bcd");
test(substring("abcd",2)  =="bcd");
test(substring("abcd",2,-3)=="");
test(substring("abcd",2,-2)=="b");
test(substring("abcd",2,-1)=="bc");

test(substring("abcd",-3,0)=="");
test(substring("abcd",-3,1)=="b");
test(substring("abcd",-3,2)=="bc");
test(substring("abcd",-3,3)=="bcd");
test(substring("abcd",-3,4)=="bcd");
test(substring("abcd",-3)  =="bcd");
test(substring("abcd",-3,-3)=="");
test(substring("abcd",-3,-2)=="b");
test(substring("abcd",-3,-1)=="bc");

test(index("abracadabra","ab")==1);
test(index("abracadabra","ab",1)==1);
test(index("abracadabra","ab",2)==8);
test(index("abracadabra","ab",7)==8);
test(index("abracadabra","ab",8)==8);
test(index("abracadabra","ab",9)=="");
test(index("abracadabra","ab",12)=="");

test(index("abracadabra","ra")==3);
test(index("abracadabra","ra",1)==3);
test(index("abracadabra","ra",2)==3);
test(index("abracadabra","ra",3)==3);
test(index("abracadabra","ra",4)==10);
test(index("abracadabra","ra",9)==10);
test(index("abracadabra","ra",10)==10);
test(index("abracadabra","ra",11)=="");
test(index("abracadabra","ra",12)=="");

test(index("abracadabra","rad")=="");

test(rindex("abracadabra","ab")==8);
test(rindex("abracadabra","ab",1)==1);
test(rindex("abracadabra","ab",2)==1);
test(rindex("abracadabra","ab",7)==1);
test(rindex("abracadabra","ab",8)==8);
test(rindex("abracadabra","ab",9)==8);
test(rindex("abracadabra","ab",12)==8);

test(rindex("abracadabra","ra")==10);
test(rindex("abracadabra","ra",1)=="");
test(rindex("abracadabra","ra",2)=="");
test(rindex("abracadabra","ra",3)==3);
test(rindex("abracadabra","ra",4)==3);
test(rindex("abracadabra","ra",9)==3);
test(rindex("abracadabra","ra",10)==10);
test(rindex("abracadabra","ra",11)==10);
test(rindex("abracadabra","ra",12)==10);

test(rindex("abracadabra","rad")=="");

test(split("abracadabra","rad")==["abracadabra"]);
test(split("abracadabra","ra")==["ab","cadab",""]);
test(split("abracadabra","ab")==["","racad","ra"]);