-
Notifications
You must be signed in to change notification settings - Fork 194
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
Project 1 Report: Making function calls work #42
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cool! I found the module system discussion particularly interesting. I'm not even sure what the right "role" of a module system in an IR is, as opposed to a user-facing language. It's worth pondering more.
Here are a few suggestions.
title = "Bril()" | ||
extra.author = "Gautam Mekkat, Eashan Garg, and Sameer Lal" | ||
extra.bio = """ | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure you have nothing to say about yourselves? 😃
""" | ||
+++ | ||
|
||
## Bril() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to duplicate your title; the template puts it there for you.
## Bril() | ||
|
||
### Goal | ||
Our goal for this project was to make function calls work. Functions reduce code duplication and allow programmers to abstract away common functionality. This simplifies the development and improves the readability of complex programs. To make functions even more useful, we introduce function parameters, return types, optional type annotations for parameters, nested function definitions, and a simple module system. We also offer the option to pass command-line arguments to the main function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I appreciate the notion, I think your audience will already be sold on the idea that functions are a good thing.
|
||
|
||
#### Adding function parameters | ||
To add support for function parameters, we first update the grammars for function definitions and calls to take whitespace-delimited lists of variable names. The interpreter's `call` operation handler first extracts the values for all arguments from the current environment map. It then pre-populates the callee's environment with the function parameters mapped to these values. This new environment is then used when evaluating the called function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you briefly discuss how function parameter declarations and call
instructions are represented in the abstract syntax, i.e., the JSON format? I'd argue that, because the JSON form is the "canonical" representation of Bril, it's more important than studying the syntax and discussing the extensions to the parser and pretty-printer for the text format, which is just for making programs easier for humans to digest.
get_hundred: int { # The ": int" is required. | ||
v0: int = const 100; | ||
ret v0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, it would be nice to discuss how this extension shows up in the abstract syntax.
} | ||
|
||
#### Nested function definitions | ||
In the above example, `lte_one` is just a helper function for `fib`and is not used anywhere else. To avoid cluttering the global function definitions, it would be nice to only define functions where they are useful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the above example, `lte_one` is just a helper function for `fib`and is not used anywhere else. To avoid cluttering the global function definitions, it would be nice to only define functions where they are useful. | |
In the above example, `lte_one` is just a helper function for `fib` and is not used anywhere else. To avoid cluttering the global function definitions, it would be nice to only define functions where they are useful. |
|
||
To do this, we introduced support for nested function definitions (i.e., function definitions within function definitions). First we add a new rule to the grammar. We add a new `instr` rule of the format `"def" func`, where `func` is the rule for normal function definitions. The `"def"` is there to avoid issues with labels (when the parser encounters `x:` it will not know if `x` is a label or a function with a return type). In the interpreter, we introduce the notion of a local function map. Previously, we had a global function map for the entire program. The local function map restricts access to a nested function to the immediate parent function. | ||
|
||
We also change the `call` operation handler to first search the local map before searching the global map. Note that this means functions can be shadowed. Below is the above program updated with nested function definitions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an elephant in the room here: are these closures? That is, can a nested function declaration access variables declared in its parent?
Or is it just a way to namespace the function declarations, and has nothing to do with nested functions as they appear in user-facing languages?
} | ||
|
||
#### Command-line arguments | ||
Adding support for command-line arguments is quite straightforward. We can use the `process.argv` variable to access arguments to `brili`. For each argument, we simply ensure that the argument is either an integer or a string containing "true" or "false", in which case we convert the string to the corresponding Boolean. We then pass these arguments to `main` the same way we would pass arguments to any other function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be nice to remind the reader here that we're talking about extending the interpreter. "Command-line arguments" don't make much sense as part of the language specification; this is just about hacking on a tool. (Right?)
} | ||
|
||
If the above program were in a file called `fib.bril`, we could run it by running: | ||
```bril2json < fib.bril | brili [n]``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the Markdown syntax you want.
### Evaluation | ||
By adding the above features to Bril, the language becomes more complex, increasing room for error. We have added many rigorous tests to ensure the correctness of our implementation. | ||
|
||
We considered benchmarking the performance of our language features but decided that this did not make much sense, as we did not have a baseline metric. We thought about comparing our language's performance to that of another interpreted language such as Python but decided that there were too many variables to consider and that our results would most likely be misleading. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks excellent; nice work!
Closes #8