{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# peforth magic command on jupyter notebook\n", "\n", "peforth supports jupyter notebook magic command ` %f ` since v1.15 _(released to Pypi on 2018.3.12)_ with both _line magic_ and _cell magic_.\n", "\n", "If you are running this jupyter notebook page online through [mybinder.org](https://mybinder.org/v2/gh/hcchengithub/peforth/master?filepath=notebook) then no installation is needed. \n", "\n", "If you would like to work on your computer, so you can save changes you made, then \n", "`pip install peforth` to install peforth and that's all, assume you already have jupyter notebook installed.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. import peforth [$^i$](#i.-The-ipython-setting-to-automatically-load-peforth-%f-magic)\n", "\n", "peforth magics are unknown to jupyter notebook at first untill we `import peforth`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "reDef unknown\n" ] } ], "source": [ "import peforth" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Hello World!\n", "\n", "Here after, in any python code cell, a `%f` leading line is interpreted as a FORTH line, called _line magic_. The next cell is an example of the `version` command that shows peforth greeting message and leaves the version number on the data stack." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "p e f o r t h v1.23\n", "source code http://github.com/hcchengithub/peforth\n", "Type 'peforth.ok()' to enter forth interpreter, 'exit' to come back.\n", "\n", " 0: 1.23 ()\n" ] } ], "source": [ "%f version .s" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!\n" ] } ], "source": [ "%f .\" Hello World!\" cr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The amazing thing here is that the ` %f ` line magic can be used in python code. . . " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!\n" ] } ], "source": [ "# use %f line magic in a python code function definition,\n", "def hi():\n", " %f .\" Hello World!\" cr\n", "\n", "# believe it or not, it works!\n", "hi()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. line magic is compiled to a python statement\n", "\n", "Now use peforth command `.source` to find out why this is possible . . . " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "def hi():\n", " get_ipython().run_line_magic('f', '.\" Hello World!\" cr')\n", "\n" ] } ], "source": [ "%f __main__ :> hi .source" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ` %f ` line magic is compiled into a python statement, that's why. [Some more explanations given at the end of this page.](#ii.-A-line-magic-command-line-compiled-to-python-statement)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4. peforth `%%f` cell magic\n", "\n", "A cell leading with a ` %%f ` (double `%%` instead of single `%` in line magic form) becomes a block of FORTH code." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5 4 3 2 1 \n" ] } ], "source": [ "\n", "%%f Nothing allowed before %%f except white spaces; everything in this line after %%f is ignored.\n", "\n", "\\ Demonstrating the peforth interpret mode [for]..[next] loop\n", "\n", "5 [for] t@ . space [next] cr\n", "\n", "\\ For experienced FORTH users\n", "\\ Where t@ is like the FORTH word r@ but it fetches TIB stack instead of the traditional \n", "\\ FORTH return stack. Because TIB is the only resource that belongs to this interpreting \n", "\\ life cycle alone." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now use the ` [for] ` loop to print a pyramid:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "*\n", "**\n", "***\n", "****\n", "*****\n", "******\n", "*******\n", "********\n", "*********\n", "**********\n", "***********\n", "************\n" ] } ], "source": [ "%%f\n", ": star .\" *\" ;\n", ": 2stars star star ;\n", ": stars for star next ;\n", "star cr 2stars cr 10 [for] 13 t@ - stars cr [next] " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5. peforth to access the __main__ name space directly\n", "\n", "Peforth and the Jupyter Notebook are of different name spaces, meaning that peforth can't see the `x` variable in the example below:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "123\n" ] } ], "source": [ "x = 123\n", "%f x . cr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The reason why we choose FORTH is for its super flexibility. Now let's redefine the way peforth handles an unknown token, i.e. the `x` of the above example. Instead of alerting `\"Error! x unknown.\"` we let it try to find the token in the Jupyter Notebook `__main__` module object. \n", "\n", "_Note: peforth v1.16 and newer version is required to play this trick. Since v1.23 the 'unknown' introduced below has become a built-in so we don't need the re-definition. Instead, use marker command '===' to forget it so the 'x' would be an 'unknown' again._" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "reDef unknown\n" ] } ], "source": [ "%%f Now we redefine the 'unknown' command (it does nothing by default)\n", "\n", ": unknown // ( token -- thing y|n) Try to find the unknown token in __main__\n", " py> getattr(sys.modules['__main__'],pop(),\"Ûnknôwn\") \n", " py> str(tos())==\"Ûnknôwn\" if drop false else true then ;\n", " \n", "\\ here after, when FORTH come accross an unknown token, instead of printing the\n", "\\ error message, it try to find the token in python __main__ module name space." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "now test again:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "abc\n", "123\n" ] } ], "source": [ "y = 'abc'\n", "%f y . cr\n", "%f x . cr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "peforth seems _know_ the 'x' and 'y' now while it doesn't. This trick is vary useful when we are studying and we can investigate things in FORTH way." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5. So where is the _muggle FORTH_ that works as a REPL shell environment?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "` peforth.ok() ` is the peforth interpreter itself. Run ` peforth.ok() ` to _shell_ a level of the FORTH interpreter and ` exit ` command to come back." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "star cr 2stars cr 10 [for] 13 t@ - stars cr [next] exit\n", "*\n", "**\n", "***\n", "****\n", "*****\n", "******\n", "*******\n", "********\n", "*********\n", "**********\n", "***********\n", "************\n", "OK " ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Run this cell to enter peforth console (REPL loop or command line interface)\n", "# Note the Out[ ] of this cell, the `[*]` indicates that the command line interface\n", "# is running. Play with it or copy-paste this line: \n", "# \"star cr 2stars cr 10 [for] 13 t@ - stars cr [next] exit\"\n", "# to try again the pyramid example above. 'exit' command to terminate.\n", "peforth.ok() " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 6. Cascading peforth exported functions\n", "\n", "` %f ` and ` %%f ` magics are actually performing the ` peforth.dictate('command lines') ` exported function, while ` peforth.ok() ` is the REPL loop of the same function. Try:\n", "\n", " peforth.dictate(\" .' hello world!' cr \") \n", " \n", "that works exactly as we have tried at first." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hello world!\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "peforth.dictate(\" .' hello world!' cr \") # Note the Out[ ] of this cell" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observed from the above outputs, `peforth.ok()` and `peforth.dictate()` both return the peforth module object. This means that we can _cascade_ these functions. The next example sees the type of the 'star' command that we definded above:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "colon\n" ] } ], "source": [ "%%f\n", "' star \\ get the word object, we defined 'star' above remember?\n", ":> type \\ get 'type' attribute of the word object\n", ". cr \\ show what we have got ... it is a 'colon' word, isn't it?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's correctly a 'colon' word. The next example in python code is actually doing the same thing as the above FORTH code:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "colon\n" ] } ], "source": [ "# Example of cascaded functions, to check a given FORTH word's type \n", "\n", "type_of_star = peforth.push('star').dictate(\"(') :> type\").pop() # cascaded functions \n", "print(type_of_star)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Where ` (') ` and ` :> ` are peforth words explained by ` help ` command as shown below. Function cascading is very useful for peforth to debug or to investigate your python target code. \n", "\n", "Peforth functions that can be called cascadedly are: ` peforth.ok() `, ` peforth.dictate() ` , ` peforth.push() ` and ` peforth.execute() `." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "( \"name\" -- Word ) name>Word like tick but the name is from TOS.\n", "\n" ] } ], "source": [ "%f help (')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "( obj -- value ) Simplified form of \"obj py> pop().foo.bar\" w/return value\n", "\tdown to the next whitespace\n", "\n" ] } ], "source": [ "%f help :> " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More information about peforth are on [the wiki of the project on Github](http://github.com/hcchengithub/peforth). \n", "\n", "May the FORTH be with you!\n", "\n", "H.C. Chen @ FigTaiwan
\n", "Last Edited: 2018.6.27
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "## Notes " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### i. The ipython setting to automatically load peforth %f magic\n", "\n", "Optionally if you want ipython to load `%f` magic automatically at startup of every jupyter notebook, so you don't need to `import peforth` explicitly everytime, what you need to do is to make . . . \n", "\n", "this config file: \n", "\n", " C:\\Users\\\\.ipython\\profile_default\\ipython_config.py (for Windows)\n", " or\n", " ~/.ipython/profile_default/ipython_config.py (for Linux) \n", " \n", "this line:\n", "\n", " # A list of dotted module names of IPython extensions to load.\n", " c.InteractiveShellApp.extensions = ['peforth']\n", "\n", "to have 'peforth' in the list as shown above." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ii. A line magic command line compiled to python statement\n", "\n", "`__main__` is a peforth word that returns the main program module object which in the current case is this jupyter notebook. `__main__` is the parent module of the funcion `hi()` and ` __main__ :> hi ` is the way peforth gets the `hi` function object. Finally ` .source ` displays the source code on top of the FORTH data stack which is now the ` hi ` function object. So this line magic:\n", "\n", " %f __main__ :> hi cr\n", " \n", "is compiled to: \n", "\n", " get_ipython().run_line_magic('f', '.\" Hello World!\" cr')\n", "\n", "Where ` 'f' ` is apparently the peforth magic command's name.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " # --- The End ---" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.0" } }, "nbformat": 4, "nbformat_minor": 2 }