-
Notifications
You must be signed in to change notification settings - Fork 4
Example 2 inline python
peforth like eforth attempts to use very basic words to build the entire forth system. Actually, peforth is started with only two words 'code' and 'end-code'.
To define a code word, we press Ctrl-D to make the Windows DOS box environment to accept multiple lines at once then type in the example and at the end drop another Ctrl-D to terminate the multiple-line input.
OK ^D
code hello
print('hello world!\n')
end-code
^D
OK hello
hello world!
OK see hello
{
"__class__": "Word",
"__module__": "peforth.projectk",
"name": "hello",
"xt": {
"__class__": "function",
"__module__": "peforth.projectk",
"name": "hello"
},
"immediate": false,
"help": "",
"comment": "",
"vid": "forth",
"wid": 243,
"type": "code"
}
------------ Source code ------------
def xt(_me=None): ### hello ###
print('hello world!\n')
-------------------------------------
OK
Where _me refers to the forth word object itself if you need to access its own attributes.
python code can be put inline mixed with forth code. This example brings you the python help() utility:
OK py: help()
Welcome to Python 3.6's help utility!
If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/3.6/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
To get a list of available modules, keywords, symbols, or topics, type
"modules", "keywords", "symbols", or "topics". Each module also comes
with a one-line summary of what it does; to list the modules whose name
or summary contain a given string such as "spam", type "modules spam".
help> quit
You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)". Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
OK
This example defines a 'dos-dir' command to go out to DOS box, run the 'dir' DOS command, and come back.
OK : dos-dir <py> import os; os.system('dir') </py> ;
OK dos-dir
Volume in drive C is Windows
Volume Serial Number is 2EA4-3202
Directory of c:\Users\hcche\Documents\GitHub\ML\machine-learning-recipes\src\part_5
2017-09-03 16:09 <DIR> .
2017-09-03 16:09 <DIR> ..
2017-06-11 08:53 240 check.py
2017-06-23 17:00 <DIR> Datasets
2017-06-11 08:53 2,218 Fisher.csv
2017-09-03 17:41 6,912 kNNClassifier.f
2017-09-01 19:45 2,256 kNNClassifier.py
2017-06-11 08:53 2,079 Part5.py
2017-09-03 16:09 <DIR> __pycache__
5 File(s) 13,705 bytes
4 Dir(s) 262,004,789,248 bytes free
OK
Now we have seen <py> ... </py> brings in a block of python code that does not return value. While <py> ... </pyV> is to envelope a python statement that returns a value back to forth's top of the data stack. We'll use it's short form py> that followed with a statement without space to get CPU information from DOS environment variable PROCESSOR_IDENTIFIER:
OK : CPU ( -- string ) // View CPU info
OK py> os.getenv('PROCESSOR_IDENTIFIER') . cr ;
OK CPU
Intel64 Family 6 Model 142 Stepping 9, GenuineIntel
OK
So py> and py: are short form of <py>...</pyV> and <py>...</py> respectively if the statement can be completed without any space in it.
This example gives the python function 'print' a FORTH variable name 'show-msg' and we can see that the value of 'show-msg' is exactly the same as the 'print' function object.
OK py> print value show-msg // ( -- func ) A function object that prints things
OK show-msg py> pop()==print . cr
True
OK
To execute a function, we use peforth commands ":>" or "::" for functions that return or not return a value:
OK py> print :: ("hi")
hi
OK py: print("hi") \ this is the form you used to see
hi
OK py> print value my-greeting // ( -- func ) Alias of the 'print' function
OK my-greeting .
<built-in function print>
OK my-greeting :: ('hi!!') \ execute the function object this way
hi!!
Now, ":>" command is similar but it returns a value:
OK py> abs .
<built-in function abs>
OK py> abs :> (-99) . cr
99
There's another way to execute a function if there's no argument for the function,
OK py: pass \ do nothing so the OK appears right next to this line
OK py: execute(print) \ print a CR so the OK appears after a blank line
OK
This execute() function is defined in projectk.py as one of the project-k VM's basic functions among friends like pop(), push(), tick(), .. etc. Whereas :: and :> are defined in peforth.f for inline python code.
:: and :> are not only for executing a function object:
OK ' + :> xt . cr \ "tick +" gets the Word object, ":> xt" gets the Word's "xt" attribute
<function xt at 0x00000208831A0D08>
OK ' + :> xt.__doc__ . cr \ To view '+' command's low level source code
def xt(_me=None): ### + ###
push(pop(1)+pop())
OK
Now use :: to modify a FORTH Word object
OK ' * :: name='multiply' \ rename the '*' command with a different name
OK rescan-word-hash \ Make peforth to refresh its word-hash
OK ' * . cr \ now tick * gets 0, meaning 'not found'. Because it's name has been changed.
0
OK 8 8 multiply . cr \
64
OK
Actually :: and :> are to do anything you do to an object. For example, to get a cell from an array:
OK py> [11,22,33] :> [2] . cr
33
OK
Or to modify a cell of an array:
OK <py> [ i for i in range(100) if i%7==0]</pyV> . cr
[0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]
OK <py> [ i for i in range(100) if i%7==0]</pyV> dup :: [3]=9999999 . cr
[0, 7, 14, 9999999, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]
So, we can manipulate python things in FORTH way, this is the most beautiful benefit. It comes with many other good things e.g. the annoying indent problem is moderated in <py>...</py> sections, if to mention only one of them.