<jupyter_start><jupyter_text>An introduction to the project-k FORTH kernel`project-k` is a very small FORTH programming language kernel supporting Javascript and Python open-sourced on GitHub https://github.com/hcchengithub/project-k. We are going to use this FORTH kernel to build our own tiny FORTH programming language system.  Read onlyRead this tutorial on GitHub https://github.com/hcchengithub/project-k/blob/master/notebooks/tutor.ipynb How to playUse an online Jupyter Notebook, I recommend [notebooks.ai](https://notebooks.ai) while [Google colab](https://colab.research.google.com), [Microsoft Azure Notebooks](https://notebooks.azure.com), and more are available out there, you don't need to install anything. Click `[Download Zip]` form GitHub project-k. We only need this notebook, `notebooks\tutor.ipynb`, and project-k source code file for Python, `projectk.py` that has only 20k bytes includes a lot of comments. Choose an online Jupyter notebook you like, create an acount, upload the minimum two files, double click or run this notebook `tutor.ipynb` and start playing.   Import the FORTH kernelThe python statement below imports `projectk.py` and gives it an arbitrary nick name `vm`. As shown below we can see that `vm` is a python module and it is an instance of `projectk.py` which is our FORTH kernel.<jupyter_code># In case you are not familiar with Jupyter Notebook, click here and press Ctrl+Enter to run this cell.
import projectk as vm
vm<jupyter_output><empty_output><jupyter_text>Python standard function `dir(obj)` gets all member names of an object. Lest's see what are in the FORTH kernel `vm`:<jupyter_code>print(dir(vm))<jupyter_output>['EXIT', 'RET', 'Word', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'code', 'comma', 'compiling', 'context', 'context_word_list', 'current', 'current_word_list', 'dictate', 'dictionary', 'docode', 'doendcode', 'endcode', 'execute', 'genfunc', 'genxt', 'here', 'inner', 'ip', 'isReDef', 'last', 'major_version', 'name', 'newhelp', 'newname', 'newxt', 'nextstring', 'nexttoken', 'ntib', 'order', 'outer', 'phaseA', 'phaseB', 'pop', 'push', 're', 'reset', 'rpop', 'rstack', 'rtos', 'stack', 'stop', 'sys', 'tib', 'tick', 'tos', 'vm', 'vocs', 'wordhash', 'words']<jupyter_text>I only want you to see that there are very few properties and methods in this FORTH kernel object and many of them are conventional FORTH tokens like `code`, `endcode`, `comma`, `compiling`, `dictionary`, `here`, `last`, `stack`, `pop`, `push`, `tos`, `rpop`, `rstack`, `rtos`, `tib`, `ntib`, `tick`, and `words`.   Now let's playThe property `vm.stack` is the FORTH data stack which is empty at first.<jupyter_code>vm.stack<jupyter_output><empty_output><jupyter_text>`vm.dictate()` method is the way project-k VM receives your commands (a string). It actually is also the way we feed it an entire FORTH source code file. Everything given to `vm.dictate()` is like a command line you type to the FORTH system as simple as only a number:<jupyter_code>vm.dictate("123")
vm.stack<jupyter_output><empty_output><jupyter_text>The first line above dictates project-k VM to push 123 onto the data stack and the second line views the data stack. We can even cascade these two lines into one:<jupyter_code>vm.dictate("456").stack<jupyter_output><empty_output><jupyter_text>because `vm.dictate()` returns the vm object itself. project-k VM knows only two words 'code' and 'end-code' at firstLet's define a FORTH command (or 'word') that prints "Hello World!!":<jupyter_code>vm.dictate("code hi! print('Hello World!!') end-code");  # define the "hi!" comamnd where print() is a standard python function
vm.dictate("hi!");<jupyter_output>Hello World!!<jupyter_text>Did you know what have we done? We defined a new FORTH code word! By the way, we can use any character in a word name except white spaces. This is a FORTH convention.   Define the 'words' command to view all wordsI'd like to see what are all the words we have so far. The FORTH command 'words' is what we want now but this tiny FORTH system does not have it yet. We have to define it:<jupyter_code>vm.dictate("code words print([w.name for w in vm.words['forth'][1:]]) end-code")
vm.dictate("words");<jupyter_output>['code', 'end-code', 'hi!', 'words']<jupyter_text>In the above definition the `vm.words` is a python dictionary (not FORTH dictionary) defined in the project-k VM object as a property which is something like an array of all recent words in the recent vocabulary named `forth` which is the only one vocabulary comes with the FORTH kernel. Where a FORTH 'vocabulary' is simply a key in python dictionary key:value pair. We have only 4 words so far as the `words` new command show above. Where 'code' and 'end-code' are built-in in the FORTH kernel; 'hi!' and 'words' were defined above.  Define '`+`' and conventional FORTH words '`.s`' , and '`s"`' Next exercise is to define some more FORTH words.<jupyter_code>vm.dictate("code + push(pop(1)+pop()) end-code");  # pop two operands from FORTH data stack and push back the result  
vm.dictate("code .s print(stack) end-code");  # print the FORTH data stack
vm.dictate('code s" push(nexttoken(\'"\'));nexttoken() end-code');  # get a string 
vm.dictate('words');  # list all recent words<jupyter_output>['code', 'end-code', 'hi!', 'words', '+', '.s', 's"']<jupyter_text>This example demonstrates how to use built-in methods `push()`, `pop()`, `nexttoken()` and the `stack` property (or global variable). As shown in above definitions, we can omit `vm.` so `vm.push`, `vm.stack` are simplified to `push`, `stack` because `code ... end-code` definitions are right in the VM name space. Now let's try these new words:<jupyter_code>vm.stack = []  # clear the data stack
vm.dictate(' s" Forth "')  # get the string 'Forth '
vm.dictate(' s" is the easist "')  # get the string 'is the easist '
vm.dictate(' s" programming langage."')  # get the string 'programing language.'
vm.dictate('.s');  # view the data stack
print(vm.dictate('+').stack)  # concatenate top two strings
print(vm.dictate('+').stack)  # concatenate the reset<jupyter_output>['Forth ', 'is the easist programming langage.']
['Forth is the easist programming langage.']<jupyter_text>The `+` command can certainly concatenate strings together and also can add numbers because Python's `+` operator works that way. Please try it with integers and floating point numbers:<jupyter_code>print(vm.dictate('123 456 + ').pop());  # Push 123, push 456, add them 
print(vm.dictate('1.23 45.6 + ').pop());<jupyter_output>579
46.83
{'fraction_non_alphanumeric': 0.12872936543995153, 'fraction_numerical': 0.005906406179009541, 'mean_word_length': 5.430379746835443, 'pattern_counts': {'":': 1, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '73681', 'license': 'MIT', 'n_tokens_mistral': 2118, 'n_tokens_neox': 2023, 'n_words': 836, 'path': 'notebooks/tutor.ipynb', 'repo_name': 'hcchengithub/project-k', 'size': '6603'}