1
votes

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)?

1
I think the type checking question is probably too broad, and the reason for the close vote. I think the AST question would be good if this question included things like the current AST data structure. - Carl
I linked to the ast, it's too clumsy to include it in the question - sam46
@Carl Also broad? i'm asking about a very specific thing how is this broad? - sam46
Not my "too broad" vote. Maybe the problem is that although the problem (assignment to function result) is clear, how to answer it is not. It seems that to answer, one would need to know how to express, in the notation you are using, that the specific Indent in the function header is the same as one which is the lvalue in an assignment in the function body. IOW, we readers don't know the "syntax of the syntax". Problem gets trickier if you want to cover Result := Interesting q, +1 - MartynA
Well After some thought I think my problem is knowing how to convert the above code to LLVM code, and I just want the algorithm - sam46

1 Answers

5
votes

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.