Companion code for paper "Imperative Functional Programs that Explain their Work", Wilmer Ricciotti, Jan Stolarek, Roly Perera and James Cheney, ICFP 2017, Oxford, UK
At the moment every TML program is just a bunch of data declarations followed by a single expression. This means that with every new binding we are nesting deeper and deeper. One potential issue with that is memory performance: evaluation is not tail-recursive and having to evaluate a single large binding probably takes more memory than evaluating a series of smaller expressions. But my main concern is a discord between compiler (well, an interpreter) and REPL. In REPL we really want to write bindings and have them added to an environment that is visible when we write subsequent expressions. So REPL is at the moment emulating existence of top-level bindings. At the same time loading normal programs into a REPL becomes pointless. That's because a program reduces to just a single expression (usually a single value of a computation) but when we load a file into REPL we want to have access to definitions of many bindings in that file. At the moment we allow loading of REPL scripts, which are files where each line contains a single let binding. This is a hacky way of having top level bindings that does not allow us to load any of our examples (unless they accidentally happen to be contain one binding per line - see also #33).
Moreover, there were several moments during development when updating REPL code to follow changes in the library was extremely painful, whereas the main compiler code required minimal or no changes. Perhaps it would be easier to maintain REPL if we had top-level bindings supported by the library and not delegated to REPL code? (Warning: that's a speculation. Haven't analysed the source code deeply enough to be certain of this).
In the early stages of my work on Slicer I proposed introducing top-level bindings but @jamescheney quite rightly pointed out that this was not the most important thing to focus on. Nevertheless, it might be of some relevance to @rolyp's internship proposal.
At the moment every TML program is just a bunch of data declarations followed by a single expression. This means that with every new binding we are nesting deeper and deeper. One potential issue with that is memory performance: evaluation is not tail-recursive and having to evaluate a single large binding probably takes more memory than evaluating a series of smaller expressions. But my main concern is a discord between compiler (well, an interpreter) and REPL. In REPL we really want to write bindings and have them added to an environment that is visible when we write subsequent expressions. So REPL is at the moment emulating existence of top-level bindings. At the same time loading normal programs into a REPL becomes pointless. That's because a program reduces to just a single expression (usually a single value of a computation) but when we load a file into REPL we want to have access to definitions of many bindings in that file. At the moment we allow loading of REPL scripts, which are files where each line contains a single let binding. This is a hacky way of having top level bindings that does not allow us to load any of our examples (unless they accidentally happen to be contain one binding per line - see also #33).
Moreover, there were several moments during development when updating REPL code to follow changes in the library was extremely painful, whereas the main compiler code required minimal or no changes. Perhaps it would be easier to maintain REPL if we had top-level bindings supported by the library and not delegated to REPL code? (Warning: that's a speculation. Haven't analysed the source code deeply enough to be certain of this).
In the early stages of my work on Slicer I proposed introducing top-level bindings but @jamescheney quite rightly pointed out that this was not the most important thing to focus on. Nevertheless, it might be of some relevance to @rolyp's internship proposal.