I'm writing a toy Pascal compiler in Haskell. I can produce a Type-annotated AST. I've been ignoring function return value assignments:
function foo : integer;
begin
foo := 12
end;
How do I handle those, given that the grammar doesn't distinguish between them and any other regular assignment statement?
Should the AST be modified to specifically highlight a return value assignment?
And how to deal with them in the type checking phase (An environment Symbol table consisting of function signatures and a stack of contexts was enough so far)?
Assignments may happen multiple times, and the Delphi dialect also allows read.
The best is to simply treat a function declaration as something that declares an implicit variable for the return variable, with its declared type.
Then you can assign and read it, and on procedure exit points (end of procedure/function or the EXIT keywords) you copy the value from the implicit variable into the register used for return values.
If the return value is complex (array, struct) and doesn't fit in a register, the typical solution is to pass the return value by an implicit var parameter. You can then use that location directly for the return variable.
Added later: for the more advanced users: functions nested within other functions are after their parents declaration, so can access their parents return value via the frame pointer they get. Pascal nested procedures can get relatively complex.