# New Ticket Created by  Jürgen Bömmels 
# Please include the string:  [perl #24224]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=24224 >


Hi,

Back in Feburary, when I hacked up macro support for IMCC I
implemented the macro_table as a static preallocated array of fixed
size and used a linear search for lookup. Now I have took the time and
transformed it to use a HASH.

The macros are now stored in a global HASH named macro_hash. They are
indexed by their name. So the lookup of a macro is a simple hash_get.
Furthermore i moved the inplace definition of the ".constant" rule to 
a support function, the definition got quite fat.

There are still some things to do:
- a global hash is still not totally right. It should be moved to the
  interpreter structure
- The size of the expansion is still limited in some way by a fixed
  buffer of size 4096. This needs to go away.

Comments
bö


-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/66091/49389/4aa72c/macro_hash.diff

Index: languages/imcc/imcc.l
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/imcc.l,v
retrieving revision 1.67
diff -u -r1.67 imcc.l
--- languages/imcc/imcc.l	14 Oct 2003 07:40:02 -0000	1.67
+++ languages/imcc/imcc.l	15 Oct 2003 16:59:31 -0000
@@ -15,6 +15,7 @@
 #include <string.h>
 #include "imc.h"
 #include "parser.h"
+#include "parrot/hash.h"
 
 #define MAX_PARAM 16
 
@@ -30,9 +31,9 @@
     int line;
 };
 
-/* XXX: boe: rework this hack to use a hash */
-struct macro_t macros[256];
-int num_macros = 0;
+/* XXX boe: This should not be global */
+HASH *macro_hash = 0;
+char *current_macro = 0;
 
 char temp_buffer[4096];
 
@@ -58,6 +59,7 @@
 static int yylex_skip (YYSTYPE *valp, void *interp, const char *skip);
 
 static int read_macro (YYSTYPE *valp, void *interp);
+static int read_constant (YYSTYPE *valp, void *interp);
 static int expand_macro (YYSTYPE *valp, void *interp, const char *name);
 static void include_file (char *file_name);
 static int in_pod;
@@ -242,31 +244,7 @@
     }
 
 <emit>".constant" {
-        int c;
-	char *name;
-	struct macro_t *m;
-
-	BEGIN(macro);
-	c = yylex_skip(valp, interp, " ");
-	if (c != IDENTIFIER)
-	    fataly(EX_SOFTWARE, sourcefile, line,
-		   "Constant names must be identifiers");
-
-	name = str_dup(valp->s);
-
-	c = yylex_skip(valp, interp, " ");
-        if (c != INTC && c != FLOATC && c != STRINGC && c != REG)
-        fataly(EX_SOFTWARE, sourcefile, line,
-        "Constant '%s' value must be a number, "
-            "stringliteral or register", name);
-
-	m = macros + num_macros++;
-	m->name = name;
-	m->expansion = str_dup (valp->s);
-	m->params.num_param = 0;
-
-	BEGIN (emit);
-	return MACRO;
+        return read_constant(valp, interp);
     }
 
 <*>".include" {
@@ -389,7 +367,6 @@
 <macro>"$"{ID}":"  return LABEL;
 <macro>".local"{WS}+ {
         char *label;
-	char *name = macros[num_macros].name;
 
 	if (yylex(valp, interp) != LABEL)
 	    fataly(EX_SOFTWARE, sourcefile, line, "LABEL expected");
@@ -397,8 +374,8 @@
 	if (valp) {
 	    YYCHOP();
 
-	    label = mem_sys_allocate(strlen(name) + yyleng + 15);
-	    sprintf(label, "local__%s__%s__$:", name, yytext+1);
+	    label = mem_sys_allocate(strlen(current_macro) + yyleng + 15);
+	    sprintf(label, "local__%s__%s__$:", current_macro, yytext+1);
 
 	    valp->s = label;
 	}
@@ -408,11 +385,10 @@
 
 <macro>".$"{ID} {
         char *label;
-	char *name = macros[num_macros].name;
 
 	if (valp) {
-	    label = mem_sys_allocate(strlen(name) + yyleng + 15);
-	    sprintf(label, "local__%s__%s__$", name, yytext+2);
+	    label = mem_sys_allocate(strlen(current_macro) + yyleng + 15);
+	    sprintf(label, "local__%s__%s__$", current_macro, yytext+2);
 
 	    valp->s = label;
 	}
@@ -570,8 +546,13 @@
 read_macro (YYSTYPE *valp, void *interp)
 {
     int c;
-    struct macro_t *m = macros + num_macros;
+    struct macro_t *m = mem_sys_allocate(sizeof(struct macro_t));
+    HASH_ENTRY value;
+    STRING *key;
     int start_cond;
+    char *last_macro = current_macro;
+
+    if (!macro_hash) new_hash(interp, &macro_hash);
 
     temp_buffer[0]='\0';
 
@@ -586,6 +567,8 @@
     m->name = valp->s;
     m->line = line;
 
+    current_macro = valp->s;
+
     /* white space is allowed between macro and opening paren) */
     c = yylex_skip(valp, interp, " ");
 
@@ -609,11 +592,56 @@
     }
     free(valp->s);
 
+    current_macro = last_macro;
+
     BEGIN(start_cond);
 
-    macros[num_macros].expansion = str_dup(temp_buffer);
+    m->expansion = str_dup(temp_buffer);
+
+    key = string_from_cstring(interp, m->name, 0);
+    value.type = enum_type_PMC;
+    value.val.pmc_val = (PMC*)m;
+    hash_put(interp, macro_hash, key, &value);
+    
+    return MACRO;
+}
+
+static int
+read_constant (YYSTYPE *valp, void *interp)
+{
+    int c;
+    char *name;
+    struct macro_t *m;
+    STRING *key;
+    HASH_ENTRY value;
+
+    if (!macro_hash) new_hash(interp, &macro_hash);
+
+    BEGIN(macro);
+    c = yylex_skip(valp, interp, " ");
+    if (c != IDENTIFIER)
+        fataly(EX_SOFTWARE, sourcefile, line,
+               "Constant names must be identifiers");
 
-    num_macros++;
+    name = str_dup(valp->s);
+
+    c = yylex_skip(valp, interp, " ");
+    if (c != INTC && c != FLOATC && c != STRINGC && c != REG)
+        fataly(EX_SOFTWARE, sourcefile, line,
+               "Constant '%s' value must be a number, "
+               "stringliteral or register", name);
+
+    m = mem_sys_allocate(sizeof(struct macro_t));
+    m->name = name;
+    m->expansion = str_dup (valp->s);
+    m->params.num_param = 0;
+
+    key = string_from_cstring(interp, m->name, 0);
+    value.type = enum_type_PMC;
+    value.val.pmc_val = (PMC*)m;
+    hash_put(interp, macro_hash, key, &value);
+
+    BEGIN (emit);
     return MACRO;
 }
 
@@ -637,15 +665,15 @@
 }
 
 static struct macro_t *
-find_macro (const char* name)
+find_macro (const char* name, void *interp)
 {
-    int i;
+    STRING *key = string_from_cstring(interp, name, 0);
+    HASH_ENTRY *value;
 
-    for (i = 0; i < num_macros; i++) {
-	if (strcmp(name, macros[i].name) == 0) return macros + i;
-    }
+    if (!macro_hash) return NULL;
 
-    return NULL;
+    value = hash_get(interp, macro_hash, key);
+    return value ? (struct macro_t *)value->val.pmc_val : NULL;
 }
 
 static int
@@ -671,7 +699,7 @@
 	return 1;
     }
 
-    m = find_macro(name);
+    m = find_macro(name, interp);
     frame->params = &m->params;
     if (m) {
         /* remember macro name for error reporting

Reply via email to