Re: multiple assignment (RKRayhawk)
6 Mar 2000 00:29:31 -0500

          From comp.compilers

Related articles
multiple assignment (Michael Larson) (2000-02-28)
Re: multiple assignment (Jens Kilian) (2000-03-06)
Re: multiple assignment (2000-03-06)
Re: multiple assignment (2000-03-06)
| List of all articles for this month |

From: (RKRayhawk)
Newsgroups: comp.compilers
Date: 6 Mar 2000 00:29:31 -0500
Organization: AOL
References: 00-02-160
Keywords: code

I have shallow experience with this but would risk a brief comment.

You are discussing parse of a pattern such as
    a = b = c + 1;

Permit me to simplify this for the part I will discuss. Lets reduce the
arithmetic expression (c+1) to simply t (think of it as a temp), so we can
focus on something else for a second... we get a conceptual
    a = b = t

In C parlance 'a' is an lvalue, and 't' is an rvalue. Your challenge is that
'b' is both an lvalue _and_ an rvalue. This kind of language facility is
sometimes called syntactic sugar. So in answer to your question
<< Is this a syntax problem?>>
This is a syntax _challenge_, not a problem with your coding or design.

The resolution is that, under some circumstances, you want the
assignment (the higher precedence assignment which is on the right) to
"return" an lvalue for the parsing process! This is a switch to a new
thinking cap, because you know that the programmer is thinking, and
you are trying to deploy an algorithm delivering, an rvalue to be
assigned in the semantics of the outer (or lower precedence)
assignment. Thus the semantics of the higher precedence (inner)
assignments is that they mean that an rvalue is returned, but the
_syntax_ is that an lvalue is returned. (Be warned that use of the
word 'returned' here can cause food fights).

So, I think, your solution is that you need two rules. First a rule that
handles simple stuff, like
    a = simple_var
Here we must evaluate simple_var once, as a rvalue.

The second rule, is something to handle the assignment pattern of
    a = assignment_expression
wherein a single program source token drives lvalue processing down in the
recurse and an rvalue in the outer handling.

You are close to that already, I think, with your posted

        : conditional_expr
        | assignment_expr '=' conditional_expr { $$ = node('=',$1,$3); }
        | ..... MULT_ASSIGN

I understand that that is an illustration of the conundrum happening
again if you recurse left, by implication you are having the problem
you describe with a rule (my conjecture) such as

        : conditional_expr
        | conditional_expr '=' assignment_expr
              { $$ = node('=',$3, $1); }
        | ..... MULT_ASSIGN

((This is my reversal, not the original poster's, this alternative is
needed to conform to C's precedence rules.))

Permit me to change some names for clarity, I am not nit picking, just
trying to narrow in on the problem. I will discard the condition_expr
(no doubt an important thing for you to keep), just to get the
presentation clear. I will add a simple_expr to make my point, by
distinguishing it from assignment_expr.

Just a sketch of simple_expr

simple_expr :
      literal {...}
  | reference_to_variable {...}
  | maybe_ref_to_function {.....}

/* the idea is anything other than an assignment
expression. */

So now assignment_expr

assignment_expr :
      legit_lvals '=' simple_expr {...}

  | legit_lvals '=' assignment_expr {...}

(There is an ouch right there with some tools, as the right recurse might not
be desirable with stack based LR tools, but that is a distraction, and maybe a
given resource challenge in C)

The issue comes down to what to hand to your
node() function. If in these two rule you pass the same thing, as in
    node('=',$1, $3)
then the hackery is necessary to pull the IDENTIFIER out of the depths
of the node that holds the symbol serving as both an lvalue and rvalue
in the complex instance (it is of course right there in the contrary
simple case).

You are, I think, doing the same thing for these two cases (although
you do not clearly post explication of " | ..... MULT_ASSIGN").

The alternative is to hand node() something different in these two
cases. This simply migrates the distinction from the code to the two
enumerated distinct rules.

So, how to do that. This is a pot shot, but I think you will see my point. In
the simple case, go ahead and continue to do
    { $$ = node('=',$1, $3); }

In the more interesting situations do something like,
    { $$ = node('=',$1, $3->down_thar); }

This simply does the lookup now at parse rule reduction time, rather
than later at hackery conditional decipherment time (in the walk of
nodes tagged with '='). It has the same effect. Permit me to tease
this out with comments that fold back to the C parlance lvalue and

assignment_expr :
      legit_lvals '=' simple_expr

    { $$ = node('=',$1, $3);
        /* hand rvalue to node constructor */
  | legit_lvals '=' assignment_expr
    { $$ = node('=',$1, $3->down_thar);
        /* hand lvalue to node constructor */
        /* call it pre-decipherment, or pre-lookup */

The use of type information in some tools, might actually force this to be
done. For example if simple_expr, and assignment_expr return distinct types,
then you might not be able to get the compiler to swallow node('=',$1, $3) for
both rules. In one instance, the $3 would be of the wrong type, and you would
have to conjure up the correct $3->whatever.

This matter might need to be generalized. Function invocations can cause lots
of disruption in the emitted code. And the tree walker will want to have the
correct thing to name in the pop for even simple
      a = function(....)
so although my sketches above put functions into the simple_expr rule

simple_expr :
  | maybe_ref_to_function {.....}

You might find this or other intricacies graduating to the more complex
assignment_expr rule enumerations.

I hope that speculation does not venture too far afield for the subset of
language facilities that you plan for your " a simple C dialect Renderman
Shading Language" .

Best Wishes,

Robert Rayhawk

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.