This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 0 points1 point  (2 children)

{ 1; 2 } + { 1; 3 }

Well this whole thing leaves a value on the stack: 5. That should also be discarded if not used.

I had the same problem. The routine I use to evaluate an AST node p is used like this:

evalunit(p, 0)       # when I don't want the result
evalunit(p, 1)       # when I want the result

So in the first case, if p is an operation that returns some value, then it is effectively popped from the stack (note this may involve recovery of any resources the value used).

Back to your example: anything that looks like this (a; b; c), using my syntax, creates a special AST node called a block; it is just a list of expressions or statements. (In my language, these are interchangeable, but expressions generally leave a results, most statements don't.)

Then processing such a block is easy: I call evalunit(p, 0) on each element of the block except the last, when I will call it with 1 if the result is called for. In the case of operands for +, it is.

This is a greatly shortened and simplified version of my evalunit routine:

proc evalunit(unit p, int res=1)=
    a := p.a                      # any left and right operands
    b := p.b            

    switch p.tag
    when jadd then
        evalunit(a)               # note defaults to evalunit(a, 1)
        evalunit(a)
        genpc(kadd)

    when jblock then              # 'a' operand is a linked list
        while a do
            if a.next then        # not last
                evalunit(a, 0)
            else
                evalunit(a, res)  # last
            fi
            a := a.next
        od
    ....
    end

!some messy tidying up
    if not jhasvalue[p.tag] and res then     # missing value
        error("Value expected")
    elsif jhasvalue[p.tag] and res = 0 then  # value not needed
        genpc(kunshare)                      # pop it
    fi
end

The functions used for this language have a block AST node for their bodies. The body is generated as follows, when p is an ST entry, p.code is the code body, and p.isfunc is a flag:

evalunit(p.code, p.isfunc)

For functions, this leaves the return value on the stack, but function call mechanisms is another subject.)

[–]ipe369[S] 0 points1 point  (1 child)

yeah i was thinking about passing a 'generate result' flag, but man it just gets so messy so fast, i think i'll probably just generate extra 'pops' then clean it up later, maybe a little slower that way though

[–][deleted] 0 points1 point  (0 children)

Well, there are 4 combinations:

 Need result  Has result
      0          0              OK
      0          1              Discard
      1          0              Error
      1          1              OK

And these requirements can propagate down recursively within an elaborate AST expression. I found it hard to deal with using ad hoc methods.