Number of Args For Function/Method Calling Implementation

classic Classic list List threaded Threaded
5 messages Options
jrd
Reply | Threaded
Open this post in threaded view
|

Number of Args For Function/Method Calling Implementation

jrd
Am curious to any thoughts on efficient implementation for arriving at the number of arguments (i.e., nArgs) required when processing a writeCall VM command.  My implementation works, but I find it pretty inefficient and "clunky."  Wondering if there's a more elegant way of handling?

In my current implementation, every time my Jack Analyzer compiles a new function/method + expression list, it tracks individual expressions within the expression list and increments a variable counter.  Then, when processing a writeCall command, it refers back to this variable counter to insert the correct number of arguments (i.e., nArgs) to use in the VM code.

That seemed simple enough...

However, the problem arises when there are additional functions/methods *within* expressions in a main function/method expression list that require more argument counting/housekeeping, etc.  For example:

do Screen.drawCircle(x, y - Math.multiply(a, Math.multiply(b, Math.multiply(c, d))), z);

Since my parser is only LL(1) grammar, it can't initially look ahead/tabulate all the various additional functions/methods (and their own internal nArgs) that may be called within a main function/method's expression list.  

So, I found that I had to keep track of multiple variable counters - one for each new, additional function/method encountered while being parsed within a main expression list.  I then had to manage all these individual variable counters in a dictionary variable referenced for writing VM code for each respective writeCall statement (and its associated nArgs).  It's almost as those I had to create "function/nArgument table" when processing an expression list - a little like a managing symbol table within a subroutine definition.

Is there a better way of handling?  For anyone who has completed this project, please let me know if you've found an alternative methodology that may be cleaner, simpler.

Thanks,

- JRD
Reply | Threaded
Open this post in threaded view
|

Re: Number of Args For Function/Method Calling Implementation

ivant
There is a better way: recursion. And if fact chapter 10 describes a recursive descent parser.

Basically, you keep all the "active" (that is, currently open) expressions on the stack. The top of the stack contains information about the current (or inner-most active) expression. When you see a sub-expression (e.g. open parentheses), the parser should call itself and parse it.
jrd
Reply | Threaded
Open this post in threaded view
|

Re: Number of Args For Function/Method Calling Implementation

jrd
Thanks for the prompt response.

However, I'm still a little confused.  My JackAnalyzer certainly does use descending recursion and calls a new compileExpression subroutine each time it processes a new expression.  All of the various active expressions are pushed to the stack.

However, my variable counter keeps track of *how many* expressions (i.e., resulting in nArgs) are needed to call on each function/method (not any actual values or information about the expressions themselves, which are pushed to the stack).  

So, I'm confused, assuming multiple "active" expressions are pushed to the stack (of which the top of the stack contains information about the inner-most active expression), don't I still need to separately keep track of how many expressions are associated with each of the individual calling functions/methods?

By way of example, in my original illustration, with all the recursive subroutines, 7 expressions would be pushed to the stack....

do Screen.drawCircle(x, y - Math.multiply(a, Math.multiply(b, Math.multiply(c, d))), z);

x, y, a, b, c, d & z would all be pushed to the stack in order (and replaced/deleted along the way as the inner functions/methods are called.)

However, noting the number of arguments (i.e., nArgs) required for each calling of Math.multiply (e.g., 2 arguments per call) and Screen.drawCircle (e.g., 3 arguments per call), I believe I have to keep track of these values of nArgs separately (in variable counter(s)) as part of properly implementing writeCall routine with collect value for nArgs.

That's the part I am trying to handle more efficiently.

Apologies if this is confusing.  However, if there is more feedback, I'd appreciate a basic example of pseudocode to help clarify - especially helpful in terms of above example.  Thanks.

- JRD

Reply | Threaded
Open this post in threaded view
|

Re: Number of Args For Function/Method Calling Implementation

cadet1620
Administrator
jrd wrote
Thanks for the prompt response.

However, I'm still a little confused.  My JackAnalyzer certainly does use descending recursion and calls a new compileExpression subroutine each time it processes a new expression.  All of the various active expressions are pushed to the stack.

However, my variable counter keeps track of *how many* expressions (i.e., resulting in nArgs) are needed to call on each function/method (not any actual values or information about the expressions themselves, which are pushed to the stack).  

So, I'm confused, assuming multiple "active" expressions are pushed to the stack...
This sounds like your expression counter is a member variable in your Compiler object.

The number of expressions in an expression list is only relevant to the active expression list. This implies that the expression counter should be a local variable in the compileExpressionList() function, and that compileExpressionList() should return that value.

--Mark
jrd
Reply | Threaded
Open this post in threaded view
|

Re: Number of Args For Function/Method Calling Implementation

jrd
Mark:

As usual on your part, another extremely insightful (and simple) solution.  As I've read, I have to try and avoid "global" object variables in as few cases as really needed!

Works perfectly and solved all issues.

Thanks again.

- JRD