{"id":37064821,"url":"https://github.com/hcchengithub/peforth","last_synced_at":"2026-01-14T07:34:50.175Z","repository":{"id":38709823,"uuid":"98887201","full_name":"hcchengithub/peforth","owner":"hcchengithub","description":"A programmable Python debugger using FORTH syntax","archived":false,"fork":false,"pushed_at":"2025-10-22T02:32:43.000Z","size":12139,"stargazers_count":35,"open_issues_count":2,"forks_count":4,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-10-22T04:26:17.997Z","etag":null,"topics":["breakpoint","debugger","forth","python","tensorflow","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hcchengithub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-07-31T12:37:05.000Z","updated_at":"2025-10-22T02:32:47.000Z","dependencies_parsed_at":"2023-02-10T20:45:27.922Z","dependency_job_id":"3764566c-2b49-4301-8df4-4cfd75f0116c","html_url":"https://github.com/hcchengithub/peforth","commit_stats":{"total_commits":260,"total_committers":2,"mean_commits":130.0,"dds":0.04230769230769227,"last_synced_commit":"8141daab5529d9dbb06e67eb815e7b42c684811c"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/hcchengithub/peforth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcchengithub%2Fpeforth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcchengithub%2Fpeforth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcchengithub%2Fpeforth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcchengithub%2Fpeforth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hcchengithub","download_url":"https://codeload.github.com/hcchengithub/peforth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcchengithub%2Fpeforth/sbom","scorecard":{"id":458582,"data":{"date":"2025-08-11","repo":{"name":"github.com/hcchengithub/peforth","commit":"9e27b9ae3864230fff573779b4b201f3ad8fe76e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-19T10:27:21.850Z","repository_id":38709823,"created_at":"2025-08-19T10:27:21.850Z","updated_at":"2025-08-19T10:27:21.850Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["breakpoint","debugger","forth","python","tensorflow","tutorial"],"created_at":"2026-01-14T07:34:49.508Z","updated_at":"2026-01-14T07:34:50.165Z","avatar_url":"https://github.com/hcchengithub.png","language":"Python","readme":"# peforth\n\n### A programmable python debugger. Set one breakpoint to x-ray everything.\n\nYou guys know how to bebug already. We all do.\nBut when it comes to Machine Learning and Tensorflow or the likes, \nthings are getting annoying if we were still using traditional debuggers.\nA programmable debugger is what in my mind and probably in yours too. \nOne breakpoint to investigate about everything! At this point, you can\nthen test whatever you want, supported by all the power of FORTH.\n\n### Debug commands in FORTH syntax\n\nSo now we need to choose an interactive UI and its syntax that \nis light weight, reliable and flexible so we won't regret of choosing it \nsomeday, has been there for decades so many people don't need to learn about \nanother new language although we are only to use some debug commands, yet easy \nenough for new users, that's FORTH. \n\n### The quickest way to try peforth online, now! \n\nAn easy way to try peforth is through the [Microsoft Azure Notebooks](https://notebooks.azure.com/). Create a [Jupyter notebook page (try mine)](https://notebooks.azure.com/hcchen1471/projects/peforthplayground) and install peforth on that page with this line:\n    \n    !pip install peforth\n    \n    # If you want to install a specific version \n    !pip install peforth==1.23\n    \n    # Install from GitHub when developping \n    pip install --force-reinstall git+https://github.com/hcchengithub/peforth.git\n    \nand then you can import peforth like this:\n\n    import peforth\n    \nand then start using peforth through magics `%f` and `%%f` as shown below: \n\n![Run peforth on Azure notebooks](http://imgsrc.baidu.com/forum/pic/item/dea32e738bd4b31ca20ded1a89d6277f9e2ff828.jpg)\n\nYou can even enter the peforth interprete state to 'talk' with it:\n\n    %f *debug* foo\u003e\n    \ndon't foget to use 'exit' command to stop talking or the page will concentrate on the dialog and not to do anything else.\n\n### Install peforth on your local computer:\n\n    pip install peforth \n\n### Magics for Jupyter Notebook\n\n`import peforth` on Jupyter Notebook is the only thing you need to do to use peforth \n`%f` and `%%f` magics.  For tutorials, please find and read jupyter notebooks in the 'notebook' directory of this project.\n\n### Run peforth:\n\nPrint \"Hello World!\"\n\n    Microsoft Windows [Version 10.0.15063]\n    (c) 2017 Microsoft Corporation. All rights reserved.\n\n    c:\\Users\\your-working-folder\u003epython -m peforth .' Hello World!!' cr bye\n    Hello World!!\n\n    c:\\Users\\your-working-folder\u003e\n\nso your peforth is working fine. \nTo your application, ``` import peforth ``` as usual to bring in the debugger:\n\n    c:\\Users\\your-working-folder\u003epython\n    Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32\n    Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n    \u003e\u003e\u003e import peforth\n    p e f o r t h    v1.07\n    source code http://github.com/hcchengithub/peforth\n    Type 'peforth.ok()' to enter forth interpreter, 'exit' to come back.\n\n    \u003e\u003e\u003e\n\nThe greeing message tells us how to enter the FORTH interpreter for your \ndebugging or investigating and how to come back to continue running your \ncode.     \n    \n### Let's try to debug a program\n    \n    # 100.py\n    \n    sum = 0\n    for i in range(100):\n        sum += i\n    print(\"The sum of 1..100 is \", sum)\n    \nRun it:\n\n    c:\\Users\\your-working-folder\u003epython 100.py\n    The sum of 1..100 is 4950\n\n    c:\\Users\\your-working-folder\u003e\n\nThe result should be 5050 but it's not! Let's drop a breakpoint \nto see what's wrong:\n\n    # 100.py with breakpoing   .----- Specify an unique command prompt to indicate where \n                               |      the breakpoint is from if there are many of them\n    import peforth             |            .----- pass locals() at the breakpoint\n    sum = 0                    |            |      to our debugger\n    for i in range(100):       |            |               .------- use a FORTH constant   \n        sum += i               |            |               |        to represent the locals()\n    peforth.ok('my first breakpoint\u003e ',loc=locals(),cmd=\"constant locals-after-the-for-loop\")\n    print(\"The sum of 1..100 is \", sum)\n\nRun again:\n    \n    c:\\Users\\your-working-folder\u003epython 100.py\n    p e f o r t h    v1.07\n    source code http://github.com/hcchengithub/peforth\n    Type 'peforth.ok()' to enter forth interpreter, 'exit' to come back.\n\n                         .--------------- at the breakpoint, type in 'words' \n                         |                command to see what have we got   \n    my first breakpoint\u003e words        .-------- It's a long list of 'words'\n    ... snip .......                  |         or available commands. Don't worry, we'll use only some of them.\n    expected_rstack expected_stack test-result [all-pass] *** all-pass [r r] [d d] [p \n    p] WshShell inport OK dir keys --- locals-after-the-for-loop\n                                           |\n                The last one is what ------' \n                we have just created throuth the breakpoint statement    \n                , named \"locals-after-the-for-loop\"\n\nLet's see it:\n\n           print a carriage return at the end -------.\n                              print the thing -----. | \n                                                   | |\n    my first breakpoint\u003e locals-after-the-for-loop . cr\n    ({'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': \n    \u003c_frozen_importlib_external.SourceFileLoader object at 0x000001DD2D737710\u003e, \n    '__spec__': None, '__annotations__': {}, '__builtins__': \u003cmodule 'builtins' \n    (built-in)\u003e, '__file__': '100.py', '__cached__': None, 'peforth': \u003cmodule 'peforth' \n    from 'C:\\\\Users\\\\hcche\\\\AppData\\\\Local\\\\Programs\\\\Python\\\\Python36\\\\lib\\\\site-packages\\\\pe\n    forth\\\\__init__.py'\u003e, 'sum': 4950, 'i': 99}, {}, 'my first breakpoint\u003e ')\n    my first breakpoint\u003e    |           |                   |\n                            |           |                   '--- our command\n               our sum -----'           |                        prompt\n                                        |                  indicates where the \n            99 instead of 100 ----------'                  breakpoint is from\n            this is the problem !!            \n\nNow leave the breakpoint and let the program continue:\n\n    my first breakpoint\u003e exit\n    my first breakpoint\u003e The sum of 1..100 is  4950\n\n    c:\\Users\\your-working-folder\u003e\n\n\n### Investigate by running experiments right at a breakpoint\n    \nWhen at a breakpoint in Tensorfow tutorials, I always want to\nmake some experiments on those frustrating *tf.something(tf.something(...),...)*\nthings to have a clearer understanding of them \nwithout leaving the underlying tutorial. Let's use the above example\nagain in another way to demonstrate how to do that with peforth:  \n\nRun peforth:\n\n    Microsoft Windows [Version 10.0.15063]\n    (c) 2017 Microsoft Corporation. All rights reserved.\n\n    c:\\Users\\hcche\\Downloads\u003epython\n    Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32\n    Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n    \u003e\u003e\u003e import peforth\n    p e f o r t h    v1.07\n    source code http://github.com/hcchengithub/peforth\n    Type 'peforth.ok()' to enter forth interpreter, 'exit' to come back.\n\n    \u003e\u003e\u003e peforth.ok()\n\n    OK   \u003c-------- Default FORTH command prompt\n    OK    \n\nAssume we are at a breakpoint and we need a procedure to\nadd 1..100 to get the sum of them. We are not sure if the procedure\nis correct so we need to try. Now copy the procedure from \nyour text editor. The ``` \u003cpy\u003e...\u003c/py\u003e ``` tells the debugger that \nthe code within is a block of in-line python. \nThe ```outport()``` function outports the given ```locals()``` to the\nFORTH environment outside the in-line python block.\n\n    \u003cpy\u003e\n    sum = 0\n    for i in range(100):\n        sum += i\n    print(\"The sum of 1..100 is \", sum)\n    outport(locals())\n    \u003c/py\u003e\n    \nIt's a block of multiple-line text strings so we press Ctrl-D\nto start a multiple-line input, copy-paste, and press another Ctrl-D\nto end the multiple-line block. Like this:\n\n    OK\n    OK ^D\n        \u003cpy\u003e\n        sum = 0\n        for i in range(100):\n            sum += i\n        print(\"The sum of 1..100 is \", sum)\n        outport(locals())\n        \u003c/py\u003e\n    ^D\n    The sum of 1..100 is  4950\n    OK\n\nNow use the 'words' command to see what have we got:\n\n    OK words\n    code end-code \\ // \u003cselftest\u003e \u003c/selftest\u003e bye /// immediate stop compyle \n    trim indent -indent \u003cpy\u003e \u003c/py\u003e \u003c/pyV\u003e words . cr help interpret-only \n    compile-only literal reveal privacy (create) : ; ( BL CR word ' , \n    [compile] py: py\u003e py:~ py\u003e~ 0branch here! here swap ! @ ? \u003er r\u003e r@ drop \n    dup over 0\u003c + * - / 1+ 2+ 1- 2- compile if then compiling char last \n    version execute cls private nonprivate (space) exit ret rescan-word-hash \n    (') branch bool and or not (forget) AND OR NOT XOR true false \"\" [] {} \n    none \u003e\u003e \u003c\u003c 0= 0\u003e 0\u003c\u003e 0\u003c= 0\u003e= = == \u003e \u003c != \u003e= \u003c= abs max min doVar doNext \n    depth pick roll space [ ] colon-word create (marker) marker next abort \n    alias \u003c\u003e public nip rot -rot 2drop 2dup invert negate within ['] allot \n    for begin until again ahead never repeat aft else while ?stop ?dup \n    variable +! chars spaces .( .\" .' s\" s' s` does\u003e count accept accept2 \n    \u003caccept\u003e nop \u003c/accept\u003e refill [else] [if] [then] (::) (:\u003e) :: :\u003e ::~ \n    :\u003e~ \"msg\"abort abort\" \"msg\"?abort ?abort\" '\u003ctext\u003e (\u003ctext\u003e) \u003ctext\u003e \u003c/text\u003e \n    \u003ccomment\u003e \u003c/comment\u003e (constant) constant value to tib. \u003et t@ t\u003e [begin] \n    [again] [until] [for] [next] modules int float drops dropall char\u003eASCII \n    ASCII\u003echar ASCII .s (*debug*) *debug* readTextFile writeTextFile \n    tib.insert sinclude include type obj\u003ekeys obj2dict stringify toString \n    .literal .function (dump) dump dump2ret d (see) .members .source see dos \n    cd slice description expected_rstack expected_stack test-result \n    [all-pass] *** all-pass [r r] [d d] [p p] WshShell inport OK dir keys \n    --- i sum\n    OK\n\nAt the end of the long list after the ``` --- ``` marker we found ``` i ``` and \n``` sum ```. They are all locals() at the point in the in-line python block.\nLet's see them:\n\n    OK i . cr\n    99\n    OK sum . cr\n    4950\n    OK\n    \nAgain, we found the root cause of why the sum is not 5050 because\n``` i ``` didn't reach to 100 as anticipated. That's exactly how the \npython ```range()``` works and that has actually confused me many times.\n\n\nVisit this project's \n[Wiki](https://github.com/hcchengithub/peforth/wiki) pages\nfor more examples about how to view MNIST handwritten digit images\nat the half way of your investigating in a Tensorflow tutorial, for\nexample, and the usages of this programmable debugger.\n\n#### Have fun!\n\nH.C. Chen, FigTaiwan \u003cbr\u003e\nhcchen_1471@hotmail.com\u003cbr\u003e\nJust undo it!\u003c/br\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhcchengithub%2Fpeforth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhcchengithub%2Fpeforth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhcchengithub%2Fpeforth/lists"}