-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
13a Functions #25
13a Functions #25
Conversation
Parsing function statementsMuch of the work has been done in parsing procedures. We'll use most of that code, take out the BYREF/BYVALUE handling. And we add in some code to handle the RETURNS: And add that to our function |
Parsing RETURN statementsRETURN statements aren't too hard to parse: Let's test that:
Result:
We haven't implemented parsing function calls yet ... |
Parsing function callsFunctions can be called anywhere a value or expression is expected. This is parsed by The first token in a function call is the function name: this is a Let's check for a Hmm ... what kind of expression should we return? |
Function expressionsWe made an early decision to represent expressions as binary expressions, with an A It looks like we do need a new kind of expression after all; a |
Resolving FUNCTION statementsThis is going to look very similar to resolving PROCEDURE statements, but with But there's a hitch: the Now our function will get Let's get back to parsing function calls. |
Instead of adding a 'returns' key to the function, resolve() it as the function 'type'
Call expressionsA call involves a function, and its arguments; that's two things. Still feels very binary. It would be a waste to make a new kind of expression, with all the complexity that adds. Let's make a simple And construct a function call as a binary expression with a
|
Resolving call expressionsOur function expression is going to be handled by Our work in [aaaac2a] made this really easy. |
Executing function declarationsHah! That's done in the resolver already: |
Evaluating function callsOkay this is the tricky part. Up to this point, So let's add some conditional evaluation: Hold on ... we forgot about RETURN statements! (We need to type-check RETURN statements against the function RETURNS.) |
Resolving return typeIt's easy enough to get the return type with the help of We don't expect to be getting RETURN statements anywhere but in a function, so we can assume Now we need to capture that return type and use it somewhere: Notice that this is the only verifier that returns something. Everything else returns |
Function calls are now handled in evaluate(). Any return value from execute()ing function stmts are captured and returned.
Back to evaluating function callsLet's execute RETURN statements: Now we can capture return values: |
Testing and bugfixWe forgot to And we also forgot to return the return value in Test code:
Result:
Annnnnd ... we have working functions 🙌 |
The previous chapter, Procedures, introduced us to many new concepts that we will need here: use of a local frame, as well as passing by value.
The 9608 pseudocode reference guide says the following for functions:
What this means for us:
evaluate()
a function as an expression with a resulting value, instead of execute()`ing it as a statementParseError
That's four mouthfuls to chew. One at a time.