{"action":"created","issue":{"url":"https://api.github.com/repos/nim-lang/Nim/issues/8927","repository_url":"https://api.github.com/repos/nim-lang/Nim","labels_url":"https://api.github.com/repos/nim-lang/Nim/issues/8927/labels{/name}","comments_url":"https://api.github.com/repos/nim-lang/Nim/issues/8927/comments","events_url":"https://api.github.com/repos/nim-lang/Nim/issues/8927/events","html_url":"https://github.com/nim-lang/Nim/issues/8927","id":358361207,"node_id":"MDU6SXNzdWUzNTgzNjEyMDc=","number":8927,"title":"[Grant Proposal] Make Nim suitable for interactive programming (Implement hot code-reloading, a REPL and a Jupyter kernel)","user":{"login":"zah","id":175462,"node_id":"MDQ6VXNlcjE3NTQ2Mg==","avatar_url":"https://avatars2.githubusercontent.com/u/175462?v=4","gravatar_id":"","url":"https://api.github.com/users/zah","html_url":"https://github.com/zah","followers_url":"https://api.github.com/users/zah/followers","following_url":"https://api.github.com/users/zah/following{/other_user}","gists_url":"https://api.github.com/users/zah/gists{/gist_id}","starred_url":"https://api.github.com/users/zah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zah/subscriptions","organizations_url":"https://api.github.com/users/zah/orgs","repos_url":"https://api.github.com/users/zah/repos","events_url":"https://api.github.com/users/zah/events{/privacy}","received_events_url":"https://api.github.com/users/zah/received_events","type":"User","site_admin":false},"labels":[{"id":32256242,"node_id":"MDU6TGFiZWwzMjI1NjI0Mg==","url":"https://api.github.com/repos/nim-lang/Nim/labels/RFC","name":"RFC","color":"1d1d1d","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-09-09T08:42:10Z","updated_at":"2018-09-09T11:15:10Z","closed_at":null,"author_association":"MEMBER","body":"This is the first grant proposal intended for the grants program made possible by the [partnership with Status to support the development of Nim](https://nim-lang.org/blog/2018/08/07/nim-partners-with-status.html). \r\n\r\nThe goal of this proposal is the implementation of hot code reloading capabilities for the native targets of Nim (C/C++/Obj-C) and consequently a REPL-like tool and a fully-functional Jupyter kernel based on these capabilities.\r\n\r\nI've recruited a suitable candidate for the grant - [Viktor Kirilov](https://github.com/onqtam), known for the creation of [doctest](https://github.com/onqtam/doctest), a popular unit-testing library for C++, and [RCRL](https://github.com/onqtam/rcrl), a REPL-like environment for C++ based on similar mechanics to the ones described here.\r\n\r\nViktor is also a [blogger](http://onqtam.com/) and an experienced conference presenter (he will be giving a [talk about RCRL later this year at CPPCON](https://cppcon2018.sched.com/event/FnJy/interactive-c-compilation-repl-done-in-a-tiny-and-embeddable-way?iframe=no&w=100%&sidebar=no&bg=no)). After completing the technical aspects of the project, he will prepare a demo program, a blog post and a technical talk promoting Nim and the newly developed capabilities. The content will be optimized to target game developers. A different volunteer will be selected to create similar promotional content intended for data scientists.\r\n\r\nThe timeframe of the grant will be 4 to 5 months of full-time work (Oct 2018 - Feb 2019, also known as Nim Winter of Code ;P). Milestones, described below, will be inspected along the way. I'll be mentoring Viktor and reviewing all of the submitted work. The proposed budget for the grant is 20,000 EUR.\r\n\r\n## Technical details of the proposal and suggested milestones\r\n\r\n#### 1. Support the `--hotCodeReloading` option in the native targets of Nim\r\n\r\nCurrently, hot code reloading is supported only the JavaScript target with semantics described in the [Nim compiler user guide](https://github.com/nim-lang/Nim/blame/devel/doc/nimc.rst#L400). This proposal intends to change the semantics to the following:\r\n\r\nThe `hotCodeReloading` option enables special compilation mode where changes in the code can be applied automatically to a running program. The code reloading happens at the granularity of an individual module. When a module is reloaded, newly added global variables will be initialized, but all the other top-level code appearing in the module won't be re-executed and the state of all existing global variables will be preserved. One can use the special event handlers `beforeCodeReload` and `afterCodeReload` to reset the state of a particular variable or to force the execution of certain statements:\r\n\r\n```nim\r\n\r\nvar\r\n settings = initTable[string, string]()\r\n lastReload: Time\r\n\r\nfor k, v in loadSettings():\r\n  settings[k] = v\r\n\r\ninitProgram()\r\n\r\nafterCodeReload:\r\n  lastReload = now()\r\n  resetProgramState()\r\n```\r\n\r\nThe code reloading event handlers can appear in any module multiple times. By default, on each code reload, Nim will execute all handlers defined in the entire program. If you want to prevent this behavior, you can guard the code though the `hasModuleChanged` magic:\r\n\r\n``` nim\r\nimport mydb\r\n\r\nvar myCache = initTable[Key, Value]()\r\n\r\nafterCodeReload:\r\n  if hasModuleChanged(mydb):\r\n    resetCache(myCache)\r\n```\r\n\r\nThe hot code reloading is based on dynamic library hot swapping in the native targets and direct manipulation of the global namespace in the JavaScript target. The Nim compiler does not specify the mechanism for detecting the conditions when the code must be reloaded. Instead, the program code is expected to call `performCodeReload()` every time it wishes to reload its code. The `hotcodereloading` module provides easy-to-use helpers for implementing hot code reloading in GUI applications, servers based on async event loops and other types of programs. The `nim-livereload` NPM package provides a convenient solution for JavaScript projects based on [LiveReload](http://livereload.com/) or [BrowserSync](https://browsersync.io/).\r\n\r\n**Rationale for the new semantics and description of the intended usage:**\r\n\r\nThe new semantics were chosen, because they are deemed more flexible than the previous ones: \r\n\r\n1) Just like before, you have a precise control of which variables and statements\r\n   will be executed on each reload.\r\n   \r\n2) You can now execute code in module `A` even when the change happens in module `B`.    You get precise control when this should happen.\r\n\r\nHow does this work in practice? You would keep your code open in your favourite text editor. If you are making a change affecting only the behavior of certain functions, you just save your code and as soon as it's recompiled you'll see the new behavior in the running program (e.g. you can modify a view function in Karax or a rendering algorithm in a game and immediately see the results on the screen. See the famous talk [Inventing on principle](https://www.youtube.com/watch?v=EGqwXt90ZqA) by Bret Victor as an inspiration). If you want to send a command to a running program, just like in a REPL environment, you can modify some of the `afterCodeReload` blocks or add a new one. The specified code will be executed immediately with the next reload. You can use this to make arbitrary manipulations to the state of your program and you can also use it to inspect the state of any variable by sending it to a logger or a visualization routine. Environments similar to [SLIME](https://www.youtube.com/watch?v=_B_4vhsmRRI) may hide this interaction behind a simpler interface that sends lines of code for execution or evaluates selected expressions interactively.\r\n\r\n**Implementation details:**\r\n\r\nThe codegen will ensure that all calls and global var references are routed through patchable jump tables. The program will be compiled to a dynamic link library (DLL, SO, etc), which will be hot swapped on each reload. It will inspect and patch the jump tables immediately after being loaded. The required indirections are expected to lead to a small, but tolerable performance hit which will affect only the development builds of the program. The initial implementation will target portable C, but some future directions will be provided for exploiting platform-specific mechanisms such as the [hot patching support](https://docs.microsoft.com/en-us/cpp/build/reference/hotpatch-create-hotpatchable-image?view=vs-2017) offered by some compilers. The initial implementation will signal any modification of a data type between two reloads as an error, but future versions may be able to support modifications to traced garbage collected objects by allocating new copies of these objects and assigning the newly added fields to a default value. Please note that the user may also use the `beforeCodeReload` and `afterCodeReload` event handlers to serialize the state of an arbitrary program to memory and then re-create it immediately after the reload.\r\n\r\n#### 2. Implement a REPL-like console for Nim\r\n\r\nIt may not be obvious, but the capabilities described in the previous section can be used to implement a REPL for Nim.\r\n\r\n1) When the REPL is started, it creates an empty program file behind the scenes.\r\n\r\n2) Each time you enter a line in the REPL, this line gets inserted either as a new global variable or inside an `afterCodeReload` handler. Entered expressions are automatically wrapped in an `echo repr(e)` call.\r\n\r\n3) The REPL is responsible for recompiling the program behind the scenes and for cleaning up all compilation artifacts after the session is over.\r\n\r\n#### 3. Implement a Jupyter kernel for Nim\r\n\r\n1) Similar to a REPL, a Jupyter kernel will just have to maintain a behind-the-scenes program file where each cell is being compiled to a function. \r\n\r\n2) Executing cells on demand is equivalent to briefly adding a `afterCodeReload` placing a call. \r\n\r\n3) A library with overloads for different types is responsible for turning the Nim expressions at the end of each cell into visualizations that can be displayed by Jupyter.\r\n\r\n#### 4. Develop an interactive demo\r\n\r\nThis may be a project based on OpenGL, where the user can interact and modify a simple 3D scene by live editing the code. Suggestions and ideas are welcome.\r\n\r\n#### 5. Blog post\r\n\r\nViktor will publish a blog post describing the features and the developed demo and try to spread the word in all the relevant communities.\r\n\r\n#### 6. Tech talk\r\n\r\nA tech talk will be prepared and proposed to a conference focusing on game development (Viktor has a background in game development and we believe this is the audience that will benefit the most from the new features).\r\n"},"comment":{"url":"https://api.github.com/repos/nim-lang/Nim/issues/comments/419708746","html_url":"https://github.com/nim-lang/Nim/issues/8927#issuecomment-419708746","issue_url":"https://api.github.com/repos/nim-lang/Nim/issues/8927","id":419708746,"node_id":"MDEyOklzc3VlQ29tbWVudDQxOTcwODc0Ng==","user":{"login":"dom96","id":246651,"node_id":"MDQ6VXNlcjI0NjY1MQ==","avatar_url":"https://avatars0.githubusercontent.com/u/246651?v=4","gravatar_id":"","url":"https://api.github.com/users/dom96","html_url":"https://github.com/dom96","followers_url":"https://api.github.com/users/dom96/followers","following_url":"https://api.github.com/users/dom96/following{/other_user}","gists_url":"https://api.github.com/users/dom96/gists{/gist_id}","starred_url":"https://api.github.com/users/dom96/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dom96/subscriptions","organizations_url":"https://api.github.com/users/dom96/orgs","repos_url":"https://api.github.com/users/dom96/repos","events_url":"https://api.github.com/users/dom96/events{/privacy}","received_events_url":"https://api.github.com/users/dom96/received_events","type":"User","site_admin":false},"created_at":"2018-09-09T11:15:10Z","updated_at":"2018-09-09T11:15:10Z","author_association":"MEMBER","body":"I also share the same concern as @zielmicha and I have an alternative proposal: extend the Nim VM to support the FFI. This not only would make ``nim secret`` into a super fast REPL but it would also mean we could get rid of all the VM-specific functions (``nimscript`` module).\r\n\r\nDid you consider this? If so, what do you think are the advantages of implementing hot code reloading instead?\r\n\r\n"}}
{"actor":{"display_login":"dom96"}}