]> thyrsus.com Git - cupl.git/commitdiff
Label resolution doesn't go crazy.
authorEric S. Raymond <esr@thyrsus.com>
Thu, 3 Nov 1994 14:58:27 +0000 (14:58 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Thu, 3 Nov 1994 14:58:27 +0000 (14:58 +0000)
cupl.h
interpret.c

diff --git a/cupl.h b/cupl.h
index ae39c014c68e5b8545adcdbac162261e7e57108e..2faeeb5b5f154c79653ba397c37382f54734df2f 100644 (file)
--- a/cupl.h
+++ b/cupl.h
@@ -54,6 +54,8 @@ typedef struct edon
 }
 node;
 
+#define for_cdr(np, tree)    for (np = tree; np; np = tree->u.n.right)
+
 /* this structure represents a CUPL value */
 typedef struct
 {
@@ -70,6 +72,7 @@ typedef struct lvar_t
     struct lvar_t      *next;          /* link to next variable */
     node               *node;          /* variable's symbol info */
     value              value;          /* variable's value */
+    node               *target;        /* target node, if label */
 
     /* information used for consistency checks */
     int                labeldef;
index 362f55b864354a04ec24c5cca334f974206afdce..0cc92dcc52905f0cd56b296b5f5827b9d7324216 100644 (file)
@@ -104,6 +104,21 @@ static void die(char *msg, ...)
     exit(1);
 }
 
+static bool recursive_apply(node *tree, bool (*fun)(node *))
+/* apply fun recursively to tree, short-circuiting on FALSE return */
+{
+    if (tree == (node *)NULL)
+       return(TRUE);
+
+    if (ATOMIC(tree->type))
+       return(fun(tree));
+    else if (recursive_apply(tree->u.n.left, fun) && recursive_apply(tree->u.n.right, fun))
+       return(fun(tree));
+    else
+       return(FALSE);
+
+}
+
 static bool r_mark_labels(node *tp)
 /* record label references */
 {
@@ -155,21 +170,6 @@ static bool r_mark_labels(node *tp)
     return(TRUE);
 }
 
-static bool recursive_apply(node *tree, bool (*fun)(node *))
-/* apply fun recursively to tree, short-circuiting on FALSE return */
-{
-    if (tree == (node *)NULL)
-       return(TRUE);
-
-    if (ATOMIC(tree->type))
-       return(fun(tree));
-    else if (recursive_apply(tree->u.n.left, fun) && recursive_apply(tree->u.n.right, fun))
-       return(fun(tree));
-    else
-       return(FALSE);
-
-}
-
 static bool check_errors(node *tree)
 /* look for inconsistencies in a program parse tree */
 {
@@ -231,6 +231,37 @@ static bool check_errors(node *tree)
     }
 }
 
+static bool r_label_rewrite(node *tp)
+/* resolve label references */
+{
+    /*
+     * KISS -- this code may do extra work, but it needs no special
+     * knowledge about node types.
+     */
+    node *left = tp->u.n.left;
+    node *right = tp->u.n.right;
+
+    if (left && left->type == IDENTIFIER && left->syminf->labelref)
+       left = left->syminf->target;
+
+    if (right && right->type == IDENTIFIER && right->syminf->labelref)
+       right = right->syminf->target;
+}
+
+static void rewrite(node *tree)
+/* resolve labels */
+{
+    node       *np;
+
+    /* first, make a pointer from each label to its destination statement */
+    for_cdr(np, tree)
+       if (np->u.n.left->type == LABEL)
+           np->u.n.left->syminf->target = np;
+
+    /* now, hack label references to eliminate name references */
+    recursive_apply(tree, r_label_rewrite);
+}
+
 void interpret(node *tree)
 /* interpret a program parse tree */
 {
@@ -241,6 +272,7 @@ void interpret(node *tree)
 
     if (check_errors(tree))
        return;
+    rewrite(tree);
 
     execute(tree);
 }