A return should stop evaluation and hand its value up, even from inside a block. Today you make that work by wrapping the returned value in a marker object that short-circuits the statement loop.
Evaluate a return statement so it stops the surrounding statements and yields its value.
return has to do something no expression does: stop the statements around it
and hand a value back up, possibly through several nested blocks. The trick is a
wrapper object - a ReturnValue holding the real value. When the statement loop
sees a result that is a ReturnValue, it stops immediately and passes that
wrapper upward instead of continuing.
That is why 9; return 2 * 5; 8; is 10 and never touches 8, and why a
return inside an if block still halts the whole program - the wrapper bubbles
out of the block’s statement loop and into the program’s. Keeping the value
wrapped as it rises matters: in the functions chapter you will unwrap it at
the function boundary so a function’s return value becomes an ordinary value to
its caller, while an early return still stops the body.
type ReturnValue struct { Value Object }// eval of a ReturnStatement wraps its value: &ReturnValue{Eval(rs.ReturnValue)}// in evalStatements, if a result is a *ReturnValue, stop the loop early// and return it, so it bubbles up through enclosing blocks