refrences
This commit is contained in:
621
references/ForthNotes/MiniForth.md
Normal file
621
references/ForthNotes/MiniForth.md
Normal file
@@ -0,0 +1,621 @@
|
||||
# MiniForth
|
||||
|
||||
**Source:** https://github.com/ttsiodras/MiniForth
|
||||
|
||||
GitHub - ttsiodras/MiniForth: A tiny Forth I built in a week. Blog post: https://www.thanassis.space/miniforth.html
|
||||
|
||||
|
||||
|
||||
[Skip to content](#start-of-content)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Navigation Menu
|
||||
|
||||
Toggle navigation
|
||||
|
||||
[Sign in](/login?return_to=https%3A%2F%2Fgithub.com%2Fttsiodras%2FMiniForth)
|
||||
|
||||
Appearance settings
|
||||
|
||||
* Platform
|
||||
|
||||
+ AI CODE CREATION
|
||||
- [GitHub CopilotWrite better code with AI](https://github.com/features/copilot)
|
||||
- [GitHub SparkBuild and deploy intelligent apps](https://github.com/features/spark)
|
||||
- [GitHub ModelsManage and compare prompts](https://github.com/features/models)
|
||||
- [MCP RegistryNewIntegrate external tools](https://github.com/mcp)
|
||||
+ DEVELOPER WORKFLOWS
|
||||
- [ActionsAutomate any workflow](https://github.com/features/actions)
|
||||
- [CodespacesInstant dev environments](https://github.com/features/codespaces)
|
||||
- [IssuesPlan and track work](https://github.com/features/issues)
|
||||
- [Code ReviewManage code changes](https://github.com/features/code-review)
|
||||
+ APPLICATION SECURITY
|
||||
- [GitHub Advanced SecurityFind and fix vulnerabilities](https://github.com/security/advanced-security)
|
||||
- [Code securitySecure your code as you build](https://github.com/security/advanced-security/code-security)
|
||||
- [Secret protectionStop leaks before they start](https://github.com/security/advanced-security/secret-protection)
|
||||
+ EXPLORE
|
||||
- [Why GitHub](https://github.com/why-github)
|
||||
- [Documentation](https://docs.github.com)
|
||||
- [Blog](https://github.blog)
|
||||
- [Changelog](https://github.blog/changelog)
|
||||
- [Marketplace](https://github.com/marketplace)
|
||||
|
||||
[View all features](https://github.com/features)
|
||||
* Solutions
|
||||
|
||||
+ BY COMPANY SIZE
|
||||
- [Enterprises](https://github.com/enterprise)
|
||||
- [Small and medium teams](https://github.com/team)
|
||||
- [Startups](https://github.com/enterprise/startups)
|
||||
- [Nonprofits](https://github.com/solutions/industry/nonprofits)
|
||||
+ BY USE CASE
|
||||
- [App Modernization](https://github.com/solutions/use-case/app-modernization)
|
||||
- [DevSecOps](https://github.com/solutions/use-case/devsecops)
|
||||
- [DevOps](https://github.com/solutions/use-case/devops)
|
||||
- [CI/CD](https://github.com/solutions/use-case/ci-cd)
|
||||
- [View all use cases](https://github.com/solutions/use-case)
|
||||
+ BY INDUSTRY
|
||||
- [Healthcare](https://github.com/solutions/industry/healthcare)
|
||||
- [Financial services](https://github.com/solutions/industry/financial-services)
|
||||
- [Manufacturing](https://github.com/solutions/industry/manufacturing)
|
||||
- [Government](https://github.com/solutions/industry/government)
|
||||
- [View all industries](https://github.com/solutions/industry)
|
||||
|
||||
[View all solutions](https://github.com/solutions)
|
||||
* Resources
|
||||
|
||||
+ EXPLORE BY TOPIC
|
||||
- [AI](https://github.com/resources/articles?topic=ai)
|
||||
- [Software Development](https://github.com/resources/articles?topic=software-development)
|
||||
- [DevOps](https://github.com/resources/articles?topic=devops)
|
||||
- [Security](https://github.com/resources/articles?topic=security)
|
||||
- [View all topics](https://github.com/resources/articles)
|
||||
+ EXPLORE BY TYPE
|
||||
- [Customer stories](https://github.com/customer-stories)
|
||||
- [Events & webinars](https://github.com/resources/events)
|
||||
- [Ebooks & reports](https://github.com/resources/whitepapers)
|
||||
- [Business insights](https://github.com/solutions/executive-insights)
|
||||
- [GitHub Skills](https://skills.github.com)
|
||||
+ SUPPORT & SERVICES
|
||||
- [Documentation](https://docs.github.com)
|
||||
- [Customer support](https://support.github.com)
|
||||
- [Community forum](https://github.com/orgs/community/discussions)
|
||||
- [Trust center](https://github.com/trust-center)
|
||||
- [Partners](https://github.com/partners)
|
||||
* Open Source
|
||||
|
||||
+ COMMUNITY
|
||||
- [GitHub SponsorsFund open source developers](https://github.com/sponsors)
|
||||
+ PROGRAMS
|
||||
- [Security Lab](https://securitylab.github.com)
|
||||
- [Maintainer Community](https://maintainers.github.com)
|
||||
- [Accelerator](https://github.com/accelerator)
|
||||
- [Archive Program](https://archiveprogram.github.com)
|
||||
+ REPOSITORIES
|
||||
- [Topics](https://github.com/topics)
|
||||
- [Trending](https://github.com/trending)
|
||||
- [Collections](https://github.com/collections)
|
||||
* Enterprise
|
||||
|
||||
+ ENTERPRISE SOLUTIONS
|
||||
- [Enterprise platformAI-powered developer platform](https://github.com/enterprise)
|
||||
+ AVAILABLE ADD-ONS
|
||||
- [GitHub Advanced SecurityEnterprise-grade security features](https://github.com/security/advanced-security)
|
||||
- [Copilot for BusinessEnterprise-grade AI features](https://github.com/features/copilot/copilot-business)
|
||||
- [Premium SupportEnterprise-grade 24/7 support](https://github.com/premium-support)
|
||||
* [Pricing](https://github.com/pricing)
|
||||
|
||||
Search or jump to...
|
||||
|
||||
|
||||
# Search code, repositories, users, issues, pull requests...
|
||||
|
||||
Search
|
||||
|
||||
Clear
|
||||
|
||||
[Search syntax tips](https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax)
|
||||
|
||||
# Provide feedback
|
||||
|
||||
We read every piece of feedback, and take your input very seriously.
|
||||
|
||||
|
||||
Include my email address so I can be contacted
|
||||
|
||||
Cancel
|
||||
Submit feedback
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Saved searches
|
||||
|
||||
## Use saved searches to filter your results more quickly
|
||||
|
||||
Name
|
||||
|
||||
Query
|
||||
|
||||
To see all available qualifiers, see our [documentation](https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax).
|
||||
|
||||
Cancel
|
||||
Create saved search
|
||||
|
||||
[Sign in](/login?return_to=https%3A%2F%2Fgithub.com%2Fttsiodras%2FMiniForth)
|
||||
|
||||
[Sign up](/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E&source=header-repo&source_repo=ttsiodras%2FMiniForth)
|
||||
|
||||
Appearance settings
|
||||
|
||||
Resetting focus
|
||||
|
||||
You signed in with another tab or window. Reload to refresh your session.
|
||||
You signed out in another tab or window. Reload to refresh your session.
|
||||
You switched accounts on another tab or window. Reload to refresh your session.
|
||||
|
||||
|
||||
|
||||
Dismiss alert
|
||||
|
||||
{{ message }}
|
||||
|
||||
[ttsiodras](/ttsiodras)
|
||||
/
|
||||
**[MiniForth](/ttsiodras/MiniForth)**
|
||||
Public
|
||||
|
||||
* [Notifications](/login?return_to=%2Fttsiodras%2FMiniForth) You must be signed in to change notification settings
|
||||
* [Fork
|
||||
7](/login?return_to=%2Fttsiodras%2FMiniForth)
|
||||
* [Star
|
||||
95](/login?return_to=%2Fttsiodras%2FMiniForth)
|
||||
|
||||
A tiny Forth I built in a week. Blog post: <https://www.thanassis.space/miniforth.html>
|
||||
|
||||
### License
|
||||
|
||||
[MIT license](/ttsiodras/MiniForth/blob/master/LICENSE)
|
||||
|
||||
[95
|
||||
stars](/ttsiodras/MiniForth/stargazers) [7
|
||||
forks](/ttsiodras/MiniForth/forks) [Branches](/ttsiodras/MiniForth/branches) [Tags](/ttsiodras/MiniForth/tags) [Activity](/ttsiodras/MiniForth/activity)
|
||||
|
||||
[Star](/login?return_to=%2Fttsiodras%2FMiniForth)
|
||||
|
||||
[Notifications](/login?return_to=%2Fttsiodras%2FMiniForth) You must be signed in to change notification settings
|
||||
|
||||
* [Code](/ttsiodras/MiniForth)
|
||||
* [Issues
|
||||
0](/ttsiodras/MiniForth/issues)
|
||||
* [Pull requests
|
||||
0](/ttsiodras/MiniForth/pulls)
|
||||
* [Actions](/ttsiodras/MiniForth/actions)
|
||||
* [Projects
|
||||
0](/ttsiodras/MiniForth/projects)
|
||||
* [Security
|
||||
0](/ttsiodras/MiniForth/security)
|
||||
* [Insights](/ttsiodras/MiniForth/pulse)
|
||||
|
||||
Additional navigation options
|
||||
|
||||
|
||||
* [Code](/ttsiodras/MiniForth)
|
||||
* [Issues](/ttsiodras/MiniForth/issues)
|
||||
* [Pull requests](/ttsiodras/MiniForth/pulls)
|
||||
* [Actions](/ttsiodras/MiniForth/actions)
|
||||
* [Projects](/ttsiodras/MiniForth/projects)
|
||||
* [Security](/ttsiodras/MiniForth/security)
|
||||
* [Insights](/ttsiodras/MiniForth/pulse)
|
||||
|
||||
# ttsiodras/MiniForth
|
||||
|
||||
master
|
||||
|
||||
[Branches](/ttsiodras/MiniForth/branches)[Tags](/ttsiodras/MiniForth/tags)
|
||||
|
||||
Go to file
|
||||
|
||||
Code
|
||||
|
||||
Open more actions menu
|
||||
|
||||
## Folders and files
|
||||
|
||||
| Name | | Name | Last commit message | Last commit date |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Latest commit History[41 Commits](/ttsiodras/MiniForth/commits/master/) 41 Commits | | |
|
||||
| [contrib](/ttsiodras/MiniForth/tree/master/contrib "contrib") | | [contrib](/ttsiodras/MiniForth/tree/master/contrib "contrib") | | |
|
||||
| [simavr @ a56b550](/buserror/simavr/tree/a56b550872906a971ac128002772d90c9e30377d "simavr") | | [simavr @ a56b550](/buserror/simavr/tree/a56b550872906a971ac128002772d90c9e30377d "simavr") | | |
|
||||
| [src](/ttsiodras/MiniForth/tree/master/src "src") | | [src](/ttsiodras/MiniForth/tree/master/src "src") | | |
|
||||
| [src\_x86](/ttsiodras/MiniForth/tree/master/src_x86 "src_x86") | | [src\_x86](/ttsiodras/MiniForth/tree/master/src_x86 "src_x86") | | |
|
||||
| [testing](/ttsiodras/MiniForth/tree/master/testing "testing") | | [testing](/ttsiodras/MiniForth/tree/master/testing "testing") | | |
|
||||
| [.gitignore](/ttsiodras/MiniForth/blob/master/.gitignore ".gitignore") | | [.gitignore](/ttsiodras/MiniForth/blob/master/.gitignore ".gitignore") | | |
|
||||
| [.gitmodules](/ttsiodras/MiniForth/blob/master/.gitmodules ".gitmodules") | | [.gitmodules](/ttsiodras/MiniForth/blob/master/.gitmodules ".gitmodules") | | |
|
||||
| [LICENSE](/ttsiodras/MiniForth/blob/master/LICENSE "LICENSE") | | [LICENSE](/ttsiodras/MiniForth/blob/master/LICENSE "LICENSE") | | |
|
||||
| [Makefile](/ttsiodras/MiniForth/blob/master/Makefile "Makefile") | | [Makefile](/ttsiodras/MiniForth/blob/master/Makefile "Makefile") | | |
|
||||
| [README.md](/ttsiodras/MiniForth/blob/master/README.md "README.md") | | [README.md](/ttsiodras/MiniForth/blob/master/README.md "README.md") | | |
|
||||
| [config.mk](/ttsiodras/MiniForth/blob/master/config.mk "config.mk") | | [config.mk](/ttsiodras/MiniForth/blob/master/config.mk "config.mk") | | |
|
||||
| View all files | | |
|
||||
|
||||
## Repository files navigation
|
||||
|
||||
* [README](#)
|
||||
* [MIT license](#)
|
||||
|
||||
*( Wrote [a blog post about this here](https://www.thanassis.space/miniforth.html) )*
|
||||
|
||||
It was raining hard, a week ago.
|
||||
|
||||
And what could you possibly do on a rainy Saturday afternoon?
|
||||
|
||||
Well...
|
||||
|
||||
You can make a Forth interpreter/compiler from scratch...
|
||||
...then put it inside a 1.5$ Blue Pill microcontroller...
|
||||
...and finally, inside an Arduino UNO...
|
||||
... within its tiny 2K RAM!
|
||||
|
||||
Click on the image to watch it blinking the LED of my Arduino:
|
||||
|
||||
[](https://www.youtube.com/watch?v=xePollbCzow)
|
||||
|
||||
I haven't done anything even *remotely* close to this in decades...
|
||||
I *loved* building it.
|
||||
|
||||
The rainy afternoon turned into a week-long hackfest *(was looking
|
||||
forward every day to the post-work FORTH-tinkering in the afternoon...)*
|
||||
|
||||
The result: a tiny, mini, micro Forth. In portable C++ :-)
|
||||
It has...
|
||||
|
||||
* basic arithmetic
|
||||
* star-slash (double-word accurate muldiv)
|
||||
* literals
|
||||
* constants
|
||||
* variables
|
||||
* direct memory access
|
||||
* string printing
|
||||
* reseting
|
||||
* comments
|
||||
* nested DO/LOOP
|
||||
* comparisons
|
||||
* nested IF/ELSE/THEN
|
||||
* ...and of course, functions (Forth words)
|
||||
|
||||
Here's an ascii-cast recording of it in action:
|
||||
|
||||
[](https://asciinema.org/a/423649?autoplay=1)
|
||||
|
||||
Read the test scenario below to see my supported Forth constructs.
|
||||
|
||||
# Portability, ArduinoSTL and Valgrind/AddressSanitizer checks
|
||||
|
||||
I meant it when I said "portable". Part of my reasoning was, that
|
||||
in addition to targeting multiple platforms (e.g. BluePill and
|
||||
Arduino) I wanted to be able to use Valgrind and AddressSanitizer
|
||||
to detect - in the host! - any issues I have with my memory handling.
|
||||
|
||||
Since I had embedded targets in mind, I tried ArduinoSTL - but it was too
|
||||
wasteful memory-wise. It also made the build process significantly slower.
|
||||
I therefore built my own [memory pool, as well as list, tuple and string-like
|
||||
C++ templates](https://github.com/ttsiodras/MiniForth/tree/master/src/mini_stl.h). It was a nice challenge, re-inventing a tiny C++ STL...
|
||||
|
||||
And I understand STL a lot better now, after building small pieces of it myself :-)
|
||||
|
||||
# Simulation / Debugging
|
||||
|
||||
I setup simulation via [simavr](https://github.com/buserror/simavr.git).
|
||||
This tremendously improved my developing speed, since a simulator
|
||||
spawns and runs much faster than the real board. Due to the code
|
||||
being portable, debugging took place mostly in the host GDB;
|
||||
and after Valgrind and AddressSanitizer gave their blessing, I usually
|
||||
found out that the simulator (and the real board) worked fine as well.
|
||||
|
||||
# BluePill vs Arduino UNO
|
||||
|
||||
Thanks to ArduinoSTL, I quickly reached the point of running inside the
|
||||
BluePill. The 1.5$ mini-monster has 10 times more SRAM than an Arduino UNO;
|
||||
so in a couple of days, I had a [working branch](https://github.com/ttsiodras/MiniForth/tree/BluePill-STM32F103C).
|
||||
|
||||
[](/ttsiodras/MiniForth/blob/master/contrib/BluePill.jpg)
|
||||
|
||||
But as said above, that wasn't nearly enough to make it work in my
|
||||
Arduino UNO. That required far more work *(see below)*.
|
||||
|
||||
As for the BluePill, I should note that, as in all my other embedded targets,
|
||||
I prefer a development workflow that is based on normal bootloaders
|
||||
*(not on programmers)*. I therefore burned the
|
||||
[stm32duino](https://github.com/rogerclarkmelbourne/STM32duino-bootloader)
|
||||
bootloader on the BluePill, which allowed me to easily program it
|
||||
in subsequent iterations via the USB connection (and a simple `make upload`).
|
||||
|
||||
The same USB connection would then function as a serial port immediately
|
||||
afterwards - allowing me to interact with the newly uploaded Forth in the
|
||||
BluePill.
|
||||
|
||||
The screenshot below is from a `tmux`: on the left, the output from `make upload`;
|
||||
and on the right, I used `picocom` to interact with my mini-Forth
|
||||
over the serial port:
|
||||
|
||||
[](/ttsiodras/MiniForth/blob/master/contrib/itworks.jpg)
|
||||
|
||||
# Memory - the final frontier
|
||||
|
||||
That covered the first two days.
|
||||
|
||||
But when I tried compiling for the Arduino UNO, I realised that the ArduinoSTL
|
||||
was not enough. I run out of memory...
|
||||
|
||||
So I built my own [mini-STL](https://github.com/ttsiodras/MiniForth/tree/master/src/mini_stl.h),
|
||||
and tightly controlled *all* memory utilisation.
|
||||
|
||||
I also used macro-magic to move all strings to Flash at compile-time
|
||||
(see `dprintf` in the code)... And saved memory everywhere I could,
|
||||
re-using error messages across various operations - and storing the
|
||||
entire array of native operations in Flash.
|
||||
|
||||
Nothing flexes your coding muscles as much as optimising; whether it is
|
||||
for speed or for space. See the implementation of ".S" for example,
|
||||
where the (obvious) stack reversal code is also the most wasteful...
|
||||
Changing it to a slower but memory-preserving algorithm allowed me
|
||||
to use ".S" even when almost all my memory is full.
|
||||
|
||||
# C++ vs C
|
||||
|
||||
I know that many developers hate C++. I even wrote a
|
||||
[blog post](https://www.thanassis.space/cpp.html) about it.
|
||||
|
||||
And I understand why - they see code like this...
|
||||
|
||||
```
|
||||
#include "mini_stl.h"
|
||||
|
||||
template<class T>
|
||||
typename forward_list<T>::box *forward_list<T>::_freeList = NULL;
|
||||
```
|
||||
|
||||
...and they start screaming - "what the hell is that", "incomprehensible
|
||||
madness", etc.
|
||||
|
||||
But there are very important benefits in using C++ - and templates
|
||||
in particular. You write less code, with no additional run-time or
|
||||
memory overhead compared to C, and with a lot more compile-time checks
|
||||
that watch your back (for things that would otherwise blow up in your face).
|
||||
|
||||
See my Optional for example, that emulates (badly) the optional
|
||||
type of Rust/OCaml/F#/Scala/Kotlin etc. It **forces** you to check
|
||||
your returned error codes:
|
||||
|
||||
```
|
||||
Optional<int> Forth::needs_a_number(const __FlashStringHelper *msg)
|
||||
{
|
||||
if (_stack.empty())
|
||||
return error(emptyMsgFlash, msg);
|
||||
auto topVal = *_stack.begin();
|
||||
if (topVal._kind == StackNode::LIT)
|
||||
return topVal._u.intVal;
|
||||
else
|
||||
return FAILURE;
|
||||
}
|
||||
```
|
||||
|
||||
You can't "forget" to check the potential for a failure coded inside
|
||||
your returned value - because your code has to "unwrap" it. I could have
|
||||
done this better, but I chose to implement it via simple tuples
|
||||
(this was a one-weeks-afternoons hack, after all :-)
|
||||
|
||||
As for the template "magic" incantation above - it *is* true magic: My
|
||||
`forward_list` template is using free-lists to store the `pop_front`-ed
|
||||
elements and reuse them in subsequent allocations. I wanted these free-lists to
|
||||
be global (i.e. static members) because lists of the same type must re-use a
|
||||
single, commonly-shared free-list. The magic spell tells the compiler I want to
|
||||
instantiate these globals *once*, for each type T that I use in any
|
||||
lists in my code.
|
||||
|
||||
# My Forth test scenario - including a FizzBuzz!
|
||||
|
||||
Yep, FizzBuzz - we are fully Turing complete. And would surely pass
|
||||
Joel's interview :-)
|
||||
|
||||
```
|
||||
." Reset... " RESET
|
||||
." Check comments... " \ Yes, we support the new-style comments :-)
|
||||
." Computing simple addition of 3 + 4... " 3 4 + .
|
||||
." Is 1 = 2 ?... " 1 2 = .
|
||||
." Is 1 > 2 ?... " 1 2 > .
|
||||
." Is 1 < 2 ?... " 1 2 < .
|
||||
." Define pi at double-word precision... " : pi 355 113 */ ;
|
||||
." Use definition to compute 10K times PI... " 10000 pi .
|
||||
." Check: 23 mod 7... " 23 7 MOD .
|
||||
." Defining 1st level function1... " : x2 2 * ;
|
||||
." Defining 1st level function2... " : p4 4 + ;
|
||||
." 2nd level word using both - must print 24... " 10 x2 p4 .
|
||||
." Defining a variable with value 123... " 123 variable ot3
|
||||
." Printing variable's value... " ot3 @ .
|
||||
." Defining The Constant (TM)... " 42 constant lifeUniverse
|
||||
." Printing The Constant (TM)... " lifeUniverse .
|
||||
." Setting the variable to The Constant (TM)... " lifeUniverse ot3 !
|
||||
." Printing variable's value... " ot3 @ .
|
||||
." Setting the variable to hex 0x11... " $11 ot3 !
|
||||
." Printing variable's value... " ot3 @ .
|
||||
." Setting the variable to binary 10100101... " %10100101 ot3 !
|
||||
." Printing variable's value... " ot3 @ .
|
||||
." Defining helper... " : p5 5 U.R . ;
|
||||
." Defining 3 times loop... " : x3lp 3 0 DO I p5 LOOP ;
|
||||
." Calling loop... " x3lp
|
||||
." Defining loop calling loop 2 times... " : x6lp 2 0 DO x3lp LOOP ;
|
||||
." Nested-looping 2x3 times... " x6lp
|
||||
." Inline: " : m 3 1 DO 3 1 DO CR J p5 I p5 ." = " J I * p5 LOOP LOOP ;
|
||||
." Use inline loops with two indexes... " m
|
||||
." Make multiples of 7 via DUP... " : m7s 10 0 DO DUP I * . LOOP DROP ;
|
||||
." Print them and DROP the 7... " 7 m7s
|
||||
." Reset... " RESET
|
||||
\ Time for Turing completeness...
|
||||
." Let's do Fizz-Buzz! " \ Turing Completeness check...
|
||||
\ fizz ( n -- 0_or_1 n )
|
||||
." Define fizz... " : fizz DUP 3 MOD 0 = IF ." fizz " 1 ELSE 0 THEN SWAP ;
|
||||
\ buzz ( n -- 0_or_1 n )
|
||||
." Define buzz... " : buzz DUP 5 MOD 0 = IF ." buzz " 1 ELSE 0 THEN SWAP ;
|
||||
\ emitNum ( 0_or_1 0_or_1 n -- )
|
||||
." Define emitNum... " : emitNum ROT ROT + 0 = if . ELSE DROP THEN ;
|
||||
\ mainloop ( n -- )
|
||||
." Define mainloop... " : mainloop ." ( " fizz buzz emitNum ." ) " ;
|
||||
\ fb ( -- )
|
||||
." Define fizzbuzz... " : fb 37 1 DO I mainloop LOOP ;
|
||||
." Run it! " fb
|
||||
." Report memory usage... " .S
|
||||
." All done! "
|
||||
```
|
||||
|
||||
# Automation
|
||||
|
||||
I am a strong believer in automation. The final form of my `Makefile`
|
||||
therefore has many rules - e.g. `make arduino-sim` - that automate
|
||||
various parts of the workflow.
|
||||
|
||||
Here's what they do:
|
||||
|
||||
* **arduino**: Compiles the code for Arduino UNO - builds `src/tmp/myforth.ino.{elf,hex}`
|
||||
* **arduino-sim**: After building, launches the compiled mini-Forth in `simduino`.
|
||||
* **upload**: After building, uploads to an Arduino attached to the port
|
||||
configured inside `config.mk`.
|
||||
* **terminal**: After uploading, launches a `picocom` terminal with
|
||||
all appropriate settings to interact with my Forth.
|
||||
* **x86**: Builds for x86. Actually, should easily build for any native target (ARM, etc).
|
||||
* **test-address-sanitizer**: Uses the x86 binary to test the code, executing
|
||||
all steps of the scenario shown above. The binary is built with the
|
||||
address sanitizer enabled (to detect memory issues).
|
||||
* **test-valgrind**: Same, but with Valgrind.
|
||||
* **test-simulator**: Spawns `simavr` and sends the entire test scenario shown
|
||||
above to it - while showing the responses received from it.
|
||||
* **test-arduino**: Sends the entire test scenario shown above to an
|
||||
Arduino Uno connected to the port specified in `config.mk`
|
||||
and shows the responses received over that serial port.
|
||||
* **blink-arduino**: Sends the "hello word" of the HW world: a tiny
|
||||
[Forth program](/ttsiodras/MiniForth/blob/master/testing/blinky.fs) blinking the Arduino's LED.
|
||||
|
||||
Another example of automation - the complete test scenario shown in the
|
||||
previous section, is not just an example in the documentation; it is
|
||||
extracted automatically from this README and fed into the Valgrind and
|
||||
AddressSanitizer tests... and also into the Python testing script that
|
||||
sends the data to the board in real-time.
|
||||
|
||||
[DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), folks.
|
||||
|
||||
# Conclusion
|
||||
|
||||
I thoroughly enjoyed building this. I know full well that Forths are not
|
||||
supposed to be built in C++; they are supposed to be built in assembly,
|
||||
and also, utilise the Flash to store the user-compiled code at run-time.
|
||||
|
||||
But that wasn't the point of this - the point was to have fun and learn Forth.
|
||||
And what better way to learn a language than to actually implement it! :-)
|
||||
|
||||
And... as a child of the 80s... I now know first-hand what
|
||||
[Jupiter Ace](https://en.wikipedia.org/wiki/Jupiter_Ace) was about :-)
|
||||
|
||||
Fork the code, and enjoy tinkering with it!
|
||||
Thanassis.
|
||||
|
||||
## About
|
||||
|
||||
A tiny Forth I built in a week. Blog post: <https://www.thanassis.space/miniforth.html>
|
||||
|
||||
### Topics
|
||||
|
||||
[arduino](/topics/arduino "Topic: arduino")
|
||||
[cpp](/topics/cpp "Topic: cpp")
|
||||
[forth](/topics/forth "Topic: forth")
|
||||
|
||||
### Resources
|
||||
|
||||
[Readme](#readme-ov-file)
|
||||
|
||||
### License
|
||||
|
||||
[MIT license](#MIT-1-ov-file)
|
||||
|
||||
### Uh oh!
|
||||
|
||||
There was an error while loading. Please reload this page.
|
||||
|
||||
[Activity](/ttsiodras/MiniForth/activity)
|
||||
|
||||
### Stars
|
||||
|
||||
[**95**
|
||||
stars](/ttsiodras/MiniForth/stargazers)
|
||||
|
||||
### Watchers
|
||||
|
||||
[**6**
|
||||
watching](/ttsiodras/MiniForth/watchers)
|
||||
|
||||
### Forks
|
||||
|
||||
[**7**
|
||||
forks](/ttsiodras/MiniForth/forks)
|
||||
|
||||
[Report repository](/contact/report-content?content_url=https%3A%2F%2Fgithub.com%2Fttsiodras%2FMiniForth&report=ttsiodras+%28user%29)
|
||||
|
||||
## [Releases 2](/ttsiodras/MiniForth/releases)
|
||||
|
||||
[Final release - optimal memory/flash use everywhere.
|
||||
|
||||
Latest
|
||||
|
||||
Jul 9, 2021](/ttsiodras/MiniForth/releases/tag/v1.1)
|
||||
|
||||
[+ 1 release](/ttsiodras/MiniForth/releases)
|
||||
|
||||
## [Packages 0](/users/ttsiodras/packages?repo_name=MiniForth)
|
||||
|
||||
No packages published
|
||||
|
||||
## Languages
|
||||
|
||||
* [C++
|
||||
80.5%](/ttsiodras/MiniForth/search?l=c%2B%2B)
|
||||
* [C
|
||||
10.9%](/ttsiodras/MiniForth/search?l=c)
|
||||
* [Makefile
|
||||
4.9%](/ttsiodras/MiniForth/search?l=makefile)
|
||||
* [Python
|
||||
1.5%](/ttsiodras/MiniForth/search?l=python)
|
||||
* [Shell
|
||||
1.3%](/ttsiodras/MiniForth/search?l=shell)
|
||||
* [Forth
|
||||
0.9%](/ttsiodras/MiniForth/search?l=forth)
|
||||
|
||||
## Footer
|
||||
|
||||
© 2026 GitHub, Inc.
|
||||
|
||||
### Footer navigation
|
||||
|
||||
* [Terms](https://docs.github.com/site-policy/github-terms/github-terms-of-service)
|
||||
* [Privacy](https://docs.github.com/site-policy/privacy-policies/github-privacy-statement)
|
||||
* [Security](https://github.com/security)
|
||||
* [Status](https://www.githubstatus.com/)
|
||||
* [Community](https://github.community/)
|
||||
* [Docs](https://docs.github.com/)
|
||||
* [Contact](https://support.github.com?tags=dotcom-footer)
|
||||
* Manage cookies
|
||||
* Do not share my personal information
|
||||
|
||||
|
||||
|
||||
You can’t perform that action at this time.
|
||||
Reference in New Issue
Block a user