Ilya Zakharevich on Thu, 19 Jan 2006 03:31:31 +0100


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

[PATCH 2.2.11+] Support for :: in identifiers


This is a beginning of "package" support in GP/PARI (installing functionality
via loaded libraries written in GP).  All this patch enables is double colon
in identifiers (as in foo::bar).

Remarks:

  a) I have no idea what this ':'-magic in filtre0() is doing.

  b) Likewise for skipdecl().

Both magics are undocumented, and not used in the test suite.  The added
support should not break them anyway, but should not they be removed
completely?

Enjoy,
Ilya

--- ./src/language/anal.c-pre	Wed Jan 18 15:48:30 2006
+++ ./src/language/anal.c	Wed Jan 18 17:59:22 2006
@@ -535,10 +535,8 @@ install(void *f, char *name, char *code)
   }
   else
   {
-    char *s = name;
-    if (isalpha((int)*s))
-      while (is_keyword_char(*++s)) /* empty */;
-    if (*s) err(talker2,"not a valid identifier", s, name);
+    if (!isalpha((int)*name) || !is_identifier(name))
+	err(talker,"not a valid identifier", name);
     ep = installep(f, name, strlen(name), EpINSTALL, 0, functions_hash + hash);
   }
   ep->code = pari_strdup(code);
@@ -782,6 +780,7 @@ type0(GEN x)
 /*                                                                 */
 /*******************************************************************/
 #define separator(c)  ((c)==';' || (compatible && (c)==':'))
+#define at_2colons(s) ((s)[0] == ':' && (s)[1] == ':' && compatible < 2)
 
 static void
 allocate_loop_err(void) {
@@ -1083,7 +1082,7 @@ expand_string(char *bp, char **ptbuf, ch
   if (is_keyword_char(*analyseur))
   {
     char *s = analyseur;
-    do s++; while (is_keyword_char(*s));
+    do s++; while (is_keyword_char(*s) || (at_2colons(s) && ++s));
 
     if ((*s == '"' || *s == ',' || *s == ')') && !is_entry(analyseur))
     { /* Do not create new user variable. Consider as a literal */
@@ -2550,7 +2549,23 @@ hashvalue(char **str)
 {
   long n = 0;
   char *s = *str;
-  while (is_key(*s)) { n = (n<<1) ^ *s; s++; }
+  while (1) {				/* alnum, "_" or "::" */
+      switch (*s) {
+      case ':':
+	  if (s[1] != ':')
+	      goto end_while;
+	  n = (n<<1) ^ *s; s++;
+	  goto eat_char;
+      default:
+	  if (!isalnum((int)*s))
+	      goto end_while;
+	  /* Fall through */
+      case '_':
+	eat_char:
+	  n = (n<<1) ^ *s; s++;
+      }
+  }
+ end_while:
   *str = s; if (n < 0) n = -n;
   return n % functions_tblsz;
 }
@@ -2587,7 +2602,7 @@ is_entry_intern(char *s, entree **table,
 int
 is_identifier(char *s)
 {
-  while (*s && is_keyword_char(*s)) s++;
+  while (*s && (is_keyword_char(*s) || (at_2colons(s) && s++))) s++;
   return *s? 0: 1;
 }
 
@@ -2885,7 +2900,8 @@ L1:
 
 static void
 skipmember(void) {
-  while (is_key((int)*analyseur)) analyseur++;
+  while (is_key((int)*analyseur) || (at_2colons(analyseur) && ++analyseur))
+      analyseur++;
 }
 
 static void
--- ./src/language/default.c-pre	Tue Nov 15 05:50:38 2005
+++ ./src/language/default.c	Wed Jan 18 18:01:28 2006
@@ -417,10 +417,10 @@ GEN
 sd_compatible(const char *v, long flag)
 {
   char *msg[] = {
-    "(no backward compatibility)",
-    "(warn when using obsolete functions)",
-    "(use old functions, don't ignore case)",
-    "(use old functions, ignore case)", NULL
+    "(no backward compatibility, allow :: in identifiers)",
+    "(warn when using obsolete functions, allow :: in identifiers)",
+    "(use old functions, don't ignore case, no :: in identifiers)",
+    "(use old functions, ignore case, no :: in identifiers)", NULL
   };
   ulong old = compatible;
   GEN r = sd_ulong(v,flag,"compatible",&compatible, 0,3,msg);
--- ./src/language/es.c-pre	Wed Nov 16 09:30:56 2005
+++ ./src/language/es.c	Wed Jan 18 17:47:24 2006
@@ -122,6 +122,10 @@ filtre0(filtre_t *F)
         break;
 
       case ':':
+	if (*s == ':') {
+	    *t++ = *s++;
+	    break;
+	}
         if (!compatible && isalpha((int)*s)) {
           t--; s++; while (is_keyword_char(*s)) { s++; }
         }
@@ -1558,7 +1562,7 @@ get_texvar(long v, char *buf, unsigned i
   if (!ep) err(talker, "this object uses debugging variables");
   s = ep->name;
   if (strlen(s) >= len) err(talker, "TeX variable name too long");
-  while(isalpha((int)*s)) *t++ = *s++;
+  while(isalpha((int)*s) || *s == ':') *t++ = *s++;
   *t = 0;
   if (isdigit((int)*s) || *s == '_') {
     int seen1 = 0, seen = 0;