Big refactor of site.
This commit is contained in:
@ -265,7 +265,7 @@ $(DEPLOY):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEPLOY)/app.yaml: $(ARDUINO)/ESP32forth-$(VERSION).zip \
|
||||
site/index.html \
|
||||
$(wildcard site/*.html) \
|
||||
site/app.yaml \
|
||||
site/eforth.go \
|
||||
$(TARGETS) | $(DEPLOY)
|
||||
@ -275,7 +275,14 @@ $(DEPLOY)/app.yaml: $(ARDUINO)/ESP32forth-$(VERSION).zip \
|
||||
cp -r $(WINDOWS)/uEf32.exe $(DEPLOY)/static/uEf32-$(VERSION).exe
|
||||
cp -r $(WINDOWS)/uEf64.exe $(DEPLOY)/static/uEf64-$(VERSION).exe
|
||||
cp -r $(RES)/eforth.ico $(DEPLOY)/static/favicon.ico
|
||||
cp -r site/static/* $(DEPLOY)/static/
|
||||
cp -r site/*.sh $(DEPLOY)
|
||||
cp -r site/*.go $(DEPLOY)
|
||||
cp -r site/*.yaml $(DEPLOY)
|
||||
sed 's/{{VERSION}}/$(VERSION)/g' site/index.html >$(DEPLOY)/index.html
|
||||
sed 's/{{VERSION}}/$(VERSION)/g' site/ESP32forth.html >$(DEPLOY)/ESP32forth.html
|
||||
sed 's/{{VERSION}}/$(VERSION)/g' site/windows.html >$(DEPLOY)/windows.html
|
||||
sed 's/{{VERSION}}/$(VERSION)/g' site/linux.html >$(DEPLOY)/linux.html
|
||||
cp site/internals.html $(DEPLOY)/
|
||||
cp site/classic.html $(DEPLOY)/
|
||||
cp -r site/.gcloudignore $(DEPLOY)
|
||||
|
||||
524
ueforth/site/ESP32forth.html
Normal file
524
ueforth/site/ESP32forth.html
Normal file
@ -0,0 +1,524 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ESP32forth</title>
|
||||
<link rel="stylesheet" href="static/eforth.css">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>ESP32forth</h1>
|
||||
|
||||
<div class="menu">
|
||||
<span class="picked"><a href="ESP32forth.html">ESP32forth</a></span>
|
||||
<span><a href="linux.html">Linux</a></span>
|
||||
<span><a href="windows.html">Windows</a></span>
|
||||
<span><a href="internals.html">Internals</a></span>
|
||||
<span><a href="classic.html">Classic</a></span>
|
||||
</div>
|
||||
|
||||
<h2>Download</h2>
|
||||
|
||||
<p>
|
||||
<a href="static/ESP32forth-{{VERSION}}.zip">ESP32forth-{{VERSION}}.zip</a>
|
||||
- Single .ino file ready for installation
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/flagxor/eforth" target="_blank">http://github.com/flagxor/eforth</a>
|
||||
- Complete Source Code (under ueforth/)
|
||||
</p>
|
||||
|
||||
<h2>Install</h2>
|
||||
|
||||
<p>
|
||||
Download the <a href="https://www.arduino.cc/en/software">Arduino IDE</a> for your platform.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go to <b>File > Preferences</b>.<br/>
|
||||
Under <b>Additional Board Manager URLs</b> enter: <code>https://dl.espressif.com/dl/package_esp32_index.json</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Choose these options under Tools.
|
||||
|
||||
<ul>
|
||||
<li><b>ESP32 Dev Module or similar (may work better with your particular board)</b>
|
||||
<ul>
|
||||
<li><b>Board:</b> ESP32 Dev Module</li>
|
||||
<li><b>Partition Scheme:</b> No OTA (2M APP, 2M SPIFFS) <b>← Non-default</b></li>
|
||||
<small>
|
||||
<li><b>Upload Speed:</b> 921600</li>
|
||||
<li><b>CPU Frequency:</b> 240MHz</li>
|
||||
<li><b>Flash Frequency:</b> 80MHz</li>
|
||||
<li><b>Flash Mode:</b> QIO</li>
|
||||
<li><b>Flash Size:</b> 4MB</li>
|
||||
<li><b>Core Debug Level:</b> None</li>
|
||||
<li><b>PSRAM:</b> Disabled</li>
|
||||
</small>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>ESP32-CAM</b>
|
||||
<ul>
|
||||
<li><b>Board:</b> AI Thinker ESP32-CAM</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2>ESP32forth Features</h2>
|
||||
|
||||
<h3>ESP32forth Specific Words</h3>
|
||||
|
||||
<h5>Null Terminated Strings</h5>
|
||||
<p>
|
||||
As null terminated strings are used throughout C interfaces,
|
||||
their use is supported in Forth by way of several non-standard
|
||||
words with the convention of using Z/z to refer to such strings
|
||||
in names and stack comments.
|
||||
</p>
|
||||
<pre>
|
||||
Z" ( "string" -- z ) Creates a null terminated string on the heap
|
||||
Z>S ( z -- a n ) Convert a null terminated string to a counted string
|
||||
S>Z ( a n -- z ) Conver a counted string string to null terminated (copies string to heap)
|
||||
</pre>
|
||||
|
||||
<h5>Raw Strings</h5>
|
||||
<p>
|
||||
Raw strings are provided better support using a string
|
||||
for the duration of the current command, without consuming heap memory.
|
||||
</p>
|
||||
<pre>
|
||||
R" ( "string" -- a n ) Creates a temporary counted string
|
||||
R| ( string| -- a n ) Creates a temporary counted string ending with |
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
DUMP ( a n -- ) Dump a memory region
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
VARIABLE ECHO -- Determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h5>Vocabularies</h5>
|
||||
<p>
|
||||
µEforth uses a hybrid of Forth-79 and Forth-83 style vocabularies.
|
||||
By default vocabularies chain to the vocabulary in which they were defined,
|
||||
as in Forth-79. However, like Forth-83, <code>ALSO</code>
|
||||
can be used to add vocabularies to a vocabulary stack of which
|
||||
<code>CONTEXT @</code> is the first item.
|
||||
The word <code>ONLY</code> clears the vocabulary stack, but as there is
|
||||
no separate ONLY vocabulary, it also sets <code>CONTEXT</code>
|
||||
to the <code>FORTH</code> vocabulary.
|
||||
The word <code>SEALED</code> modifies the most recently defined vocabulary
|
||||
such that it does not chain. Note, this must be done before words are added to it.
|
||||
</p>
|
||||
<pre>
|
||||
VOCABULARY ( "name" ) Create a vocabulary with the current vocabulary as parent
|
||||
FORTH ( -- ) Make the FORTH vocabulary the context vocabulary
|
||||
DEFINITIONS ( -- ) Make the context vocabulary the current vocabulary
|
||||
VLIST ( -- ) List the words in the context vocabulary (not chains)
|
||||
WORDS ( -- ) List the words in the context vocabulary (including chains)
|
||||
TRANSFER ( "name" ) Move a word from its current dictionary to the current vocabulary
|
||||
Useful for "hiding" built-in words
|
||||
ALSO ( -- ) Duplicate the vocabulary at the top of the vocabulary stack
|
||||
ONLY ( -- ) Reset context stack to one item, the FORTH dictionary
|
||||
Non-standard, as there's no distinct ONLY vocabulary
|
||||
ORDER ( -- ) Print the vocabulary search order
|
||||
SEALED ( -- ) Alter the last vocabulary defined so it doesn't chain
|
||||
</pre>
|
||||
|
||||
<h5>Blocks</h5>
|
||||
<pre>
|
||||
USE ( "name" -- ) Use "name" as the blockfile, e.g. USE /spiffs/foo
|
||||
OPEN-BLOCKS ( a n -- ) Open a file as the block file
|
||||
LOAD ( n -- ) Evaluate a block
|
||||
THRU ( a b -- ) Load blocks a thru b
|
||||
LIST ( n -- ) List a block
|
||||
BLOCK ( n -- a ) Get a 1024 byte block
|
||||
BUFFER ( n -- a ) Get a 1024 byte block without regard to old contents
|
||||
UPDATE ( -- ) Mark the last block modified
|
||||
FLUSH ( -- ) Save and empty all buffers
|
||||
EMPTY-BUFFERS ( -- ) Empty all buffers
|
||||
SAVE-BUFFERS ( -- ) Save all buffers
|
||||
SCR ( -- a ) Pointer to last listed block
|
||||
</pre>
|
||||
|
||||
<h5>Block Editor</h5>
|
||||
These words are available inside the <code>EDITOR</code> vocabulary.
|
||||
<pre>
|
||||
WIPE ( -- ) Blank out the current block
|
||||
L ( -- ) List the current block
|
||||
D ( n -- ) Delete a line in the current block
|
||||
E ( n -- ) Clear a line in the current block
|
||||
R ( n "text" -- ) Replace a line in the current block
|
||||
A ( n "text" -- ) Add (insert) a line in the current block
|
||||
P ( -- ) Move to the previous block
|
||||
N ( -- ) Move to the next block
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
ECHO ( -- a ) -- Address of flag that determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h3>ESP32forth Opcodes</h3>
|
||||
|
||||
<p>
|
||||
Because Arduino builds a statically linked image for flashing into ESP32 devices,
|
||||
all C function bindings need to be explicitly added.
|
||||
This is the current collection.
|
||||
Typically to reduce confusion, function names have be preserved even through verbose.
|
||||
In popular cases a shorted higher level name is provided.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/arduino/arduino.template.ino">arduino.template.ino</a>.
|
||||
</p>
|
||||
|
||||
<h5>Allocation</h5>
|
||||
These words are inside the <code>internals</code> vocabulary.
|
||||
<pre>
|
||||
MALLOC ( n -- a | 0 ) System malloc
|
||||
SYSFREE ( a -- ) System free
|
||||
REALLOC ( a n -- a | 0 ) System realloc
|
||||
</pre>
|
||||
|
||||
<h5>Serial</h5>
|
||||
These words are inside the <code>Serial</code> vocabulary.
|
||||
<pre>
|
||||
Serial.begin ( baud -- ) Start serial port
|
||||
Serial.end ( -- ) End serial port
|
||||
Serial.available ( -- f ) Is serial data available
|
||||
Serial.readBytes ( a n -- n ) Read serial bytes, return number gotten
|
||||
Serial.write ( a n -- n ) Write serial bytes
|
||||
Serial.flush ( -- ) Flush serial buffer
|
||||
</pre>
|
||||
|
||||
<h5>Serial Bluetooth</h5>
|
||||
These words are inside the <code>bluetooth</code> vocabulary.
|
||||
<pre>
|
||||
SerialBT.new ( -- bt ) Allocate new BT object
|
||||
SerialBT.delete ( bt -- ) Free BT object
|
||||
SerialBT.begin ( localname ismaster bt -- f )
|
||||
SerialBT.end ( bt -- )
|
||||
SerialBT.available ( bt -- f )
|
||||
SerialBT.readBytes ( a n bt -- n )
|
||||
SerialBT.write ( a n bt -- n )
|
||||
SerialBT.flush ( bt -- )
|
||||
SerialBT.hasClient ( bt -- f )
|
||||
SerialBT.enableSSP ( bt -- )
|
||||
SerialBT.setPin ( z bt -- f )
|
||||
SerialBT.unpairDevice ( addr bt -- f )
|
||||
SerialBT.connect ( remotename bt -- f )
|
||||
SerialBT.connectAddr ( addr bt -- f )
|
||||
SerialBT.disconnect ( bt -- f )
|
||||
SerialBT.connected ( timeout bt -- f )
|
||||
SerialBT.isReady ( checkMaster timeout -- f ) Default checkMaster=false, timeout=0
|
||||
</pre>
|
||||
|
||||
<h5>Bluetooth</h5>
|
||||
These words are inside the <code>bluetooth</code> vocabulary.
|
||||
<pre>
|
||||
esp_bt_dev_get_address ( -- a ) addr of 6 byte mac address
|
||||
</pre>
|
||||
|
||||
<h5>GPIO</h5>
|
||||
<pre>
|
||||
pinMode ( pin mode -- ) Set GPIO pin mode
|
||||
digitalWrite ( pin value -- ) Set GPIO pin state
|
||||
analogRead ( pin -- n ) Analog read from 0-4095
|
||||
</pre>
|
||||
|
||||
<h5>ledc</h5>
|
||||
These words are inside the <code>ledc</code> vocabulary.
|
||||
<pre>
|
||||
ledcSetup ( channel freq resolution -- freq )
|
||||
ledcAttachPin ( pin channel -- )
|
||||
ledcDetachPin ( pin -- )
|
||||
ledcRead ( channel -- n )
|
||||
ledcReadFreq ( channel -- freq ) Get frequency (x 1,000,000)
|
||||
ledcWrite ( channel duty -- )
|
||||
ledcWriteTone ( channel freq ) Write tone frequency (x 1000)
|
||||
ledcWriteNote ( channel note octave -- freq )
|
||||
</pre>
|
||||
|
||||
<h5>Short GPIO Names</h5>
|
||||
<pre>
|
||||
pin ( value pin# -- ) Set GPIO pin value
|
||||
adc ( pin# -- n ) Analog read pin, result 0-1023
|
||||
</pre>
|
||||
|
||||
<h5>System</h5>
|
||||
<pre>
|
||||
MS ( n -- )
|
||||
TERMINATE ( n -- ) Call system exit
|
||||
</pre>
|
||||
|
||||
<h5>Files</h5>
|
||||
<pre>
|
||||
R/O ( -- mode )
|
||||
R/W ( -- mode )
|
||||
W/O ( -- mode )
|
||||
BIN ( mode -- mode )
|
||||
CLOSE-FILE ( fh -- ior )
|
||||
OPEN-FILE ( a n mode -- fh ior )
|
||||
CREATE-FILE ( a n mode -- fh ior )
|
||||
DELETE-FILE ( a n -- ior )
|
||||
WRITE-FILE ( a n fh -- ior )
|
||||
READ-FILE ( a n fh -- n ior )
|
||||
FILE-POSITION ( fh -- n ior )
|
||||
REPOSITION-FILE ( n fh -- ior )
|
||||
FILE-SIZE ( fh -- n ior )
|
||||
</pre>
|
||||
|
||||
<h5>WiFi</h5>
|
||||
These words are inside the <code>WiFi</code> vocabulary.
|
||||
<pre>
|
||||
WiFi.config ( ip dns gateway subnet -- ) Packaged a.b.c.d little-endian
|
||||
Wifi.begin ( ssid-z password-z -- )
|
||||
Wifi.disconnect ( -- )
|
||||
WiFi.status ( -- n )
|
||||
WiFi.macAddress ( a -- )
|
||||
WiFi.localIP ( -- ip )
|
||||
WiFi.mode ( mode -- ) WIFI_MODE_NULL WIFI_MODE_STA WIFI_MODE_AP WIFI_MODE_APSTA
|
||||
WiFi.setTxPower ( powerx4 -- ) Set power x4
|
||||
WiFi.getTxPower ( -- powerx4 ) Get power x4
|
||||
</pre>
|
||||
|
||||
<h5>mDNS</h5>
|
||||
<pre>
|
||||
MDNS.begin ( name-z -- ) Start multicast dns
|
||||
</pre>
|
||||
|
||||
<h5>SPIFFS</h5>
|
||||
These words are inside the <code>SPIFFS</code> vocabulary.
|
||||
<pre>
|
||||
SPIFFS.begin ( format-on-fail path-z max-files -- f )
|
||||
SPIFFS.end ( -- )
|
||||
SPIFFS.format ( -- f )
|
||||
SPIFFS.totalBytes ( -- n )
|
||||
SPIFFS.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h5>WebServer</h5>
|
||||
These words are inside the <code>WebServer</code> vocabulary.
|
||||
<pre>
|
||||
WebServer.new ( port -- ws ) Allocate new webserver object
|
||||
WebServer.delete ( ws -- ) Delete webserver object
|
||||
WebServer.begin ( port ws -- )
|
||||
WebServer.stop ( ws -- )
|
||||
WebServer.on ( path-z xt ws -- ) Set up a web path handle callback
|
||||
WebServer.handleClient ( ws -- ) Handle one client request
|
||||
WebServer.hasArg ( z ws -- f ) By name
|
||||
WebServer.arg ( z ws -- z ) By name
|
||||
WebServer.argi ( n ws -- z ) By index
|
||||
WebServer.argName ( n ws -- z) By index
|
||||
WebServer.args ( ws -- n ) Number of args
|
||||
WebServer.setContentLength ( n ws -- )
|
||||
WebServer.sendHeader ( name-z value-z fist ws -- )
|
||||
WebServer.send ( code mimetype data ws -- )
|
||||
WebServer.sendContent ( z ws -- )
|
||||
WebServer.method ( ws -- n ) GET / POST etc.
|
||||
</pre>
|
||||
|
||||
<h5>Wire</h5>
|
||||
These words are inside the <code>Wire</code> vocabulary.
|
||||
<pre>
|
||||
Wire.begin ( -- f )
|
||||
Wire.setPins ( sda scl -- f )
|
||||
Wire.setClock ( frequency -- )
|
||||
Wire.getClock ( -- frequency )
|
||||
Wire.setTimeout ( ms -- ) Default is 50ms
|
||||
Wire.getTimeout ( -- ms )
|
||||
Wire.lastError ( -- n )
|
||||
Wire.getErrorText ( n -- z )
|
||||
Wire.beginTransmission ( n -- )
|
||||
Wire.endTransmission ( sendstop -- f )
|
||||
Wire.requestFrom ( address quantity sendstop -- n )
|
||||
Wire.writeTransmission ( addr a n sendstop -- err )
|
||||
Wire.readTransmission ( addr a n sendstop acount -- err )
|
||||
Wire.write ( a n -- n )
|
||||
Wire.available ( -- f )
|
||||
Wire.read ( -- ch )
|
||||
Wire.peek ( -- ch )
|
||||
Wire.busy ( -- f )
|
||||
Wire.flush ( -- )
|
||||
</pre>
|
||||
|
||||
<h5>Camera</h5>
|
||||
These words are inside the <code>camera</code> vocabulary.
|
||||
<pre>
|
||||
esp_camera_init ( config -- f )
|
||||
esp_camera_deinit ( -- f )
|
||||
esp_camera_fb_get ( -- fb )
|
||||
esp_camera_fb_return ( fb -- )
|
||||
esp_camera_sensor_get ( -- sensor )
|
||||
</pre>
|
||||
|
||||
<h5>SD_MMC</h5>
|
||||
These words are inside the <code>SD_MMC</code> vocabulary.
|
||||
<pre>
|
||||
SD_MMC.begin ( mount mode1bit ) default mode1bit=false
|
||||
SD_MMC.end ( -- )
|
||||
SD_MMC.cardType ( -- n )
|
||||
SD_MMC.totalBytes ( -- n )
|
||||
SD_MMC.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h3 id="webui">ESP32 WebUI</h3>
|
||||
|
||||
<p>
|
||||
A terminal over the web can be activated.
|
||||
Contact at port printed or via mDNS <a href="http://ueforth/">http://ueforth/</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
webui ( network-z password-z -- )
|
||||
</pre>
|
||||
|
||||
<p>Usage:</p>
|
||||
|
||||
<pre>
|
||||
z" NETWORK-NAME" z" PASSWORD" webui
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/arduino/arduino_server.fs">arduino_server.fs</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="autoexec">Autoexec.fs</h3>
|
||||
|
||||
<p>
|
||||
The system will automatically attempt to mount SPIFFS filesystem at <code>/spiffs</code>.
|
||||
It will then at start attempt to load <code>/spiffs/autoexec.fs</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One way this feature can be used to configure the Web UI to start by default.
|
||||
When doing this, be sure to test your Web UI settings work well first.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
r| z" NETWORK-NAME" z" PASSWORD" webui | s" /spiffs/autoexec.fs" dump-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To remove a previously configured <code>autoexec.fs</code> you will need
|
||||
to be able to reboot in a mode with Forth. One way to do this is to search
|
||||
for the line in the .ino file that refers to <code>autoexec.fs</code>
|
||||
and replace it with a different name. Then run the following:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s" /spiffs/autoexec.fs" delete-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/arduino/autoboot.fs">autoboot.fs</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="adding_words">Adding Words</h3>
|
||||
|
||||
<p>
|
||||
Adding words based on C functions can be done by editing the source code.
|
||||
For ESP32forth <code>arduino.template.ino</code> is the appropriate place.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Because of the use of <a href="https://en.wikipedia.org/wiki/X_Macro">X-Macros</a> words can be
|
||||
added in as little as one line. Locate the macro called <code>PLATFORM_OPCODE_LIST</code>
|
||||
and add your words there.
|
||||
</p>
|
||||
|
||||
<p>NOTE: Be careful to end each line with a \ so the macros will chain correctly.</p>
|
||||
|
||||
<p>
|
||||
To add a word containing only letters, numbers, and underscore you can use <code>Y</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(MY_WORD123, c_function_to_call()) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If your word name contains other characters, instead use <code>X</code>.
|
||||
You will need to make up an alternate name for the middle parameter.
|
||||
It must contain only letters, numbers, and underscore.
|
||||
The name is not used anywhere else, but must be unique.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
X("myword!", MY_WORD_BANG, c_function_to_call()) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Values from the data stack can be accessed via
|
||||
the variables <code>tos</code> (Top of Stack) and
|
||||
<code>sp</code> (Pointer to the rest of the stack).
|
||||
The stack has the data type <code>cell_t</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can push a value of any type to the stack with the macro <code>PUSH</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(MY_WORD, PUSH calculate_magic_value()) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To simplify calling C functions, you can also refer to elements on the stack
|
||||
with the types positional names:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
n10 n9 n8 n7 n6 n5 n4 n3 n2 n1 n0 - Access stack as cell_t integer values
|
||||
c4 c3 c2 c1 c0 - Access stack as char* values
|
||||
b4 b3 b2 b1 b0 - Access stack as uint8_t* byte values
|
||||
a4 a3 a2 a1 a0 - Access stack as void* values
|
||||
|
||||
Examples:
|
||||
void send_message(const char *message, int code);
|
||||
...
|
||||
X("send-message", SEND_MESSAGE, send_message(c1, n0)) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You can always replace the top item on the stack with <code>SET</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(DECODE, SET decode_func(n0)) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You can drop elements from the stack with <code>DROP</code>
|
||||
or <code>DROPn(number)</code>.
|
||||
You can nip elements from below top of the stack with <code>NIP</code>
|
||||
or <code>NIPn(number)</code>.
|
||||
Be aware that like <code>PUSH</code> this will cause stack indices to change.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int my_cool_function(char *foo, int bar, uint8_t *baz);
|
||||
...
|
||||
Y(MY_FUNC, n0 = my_cool_function(c2, n1, b0); NIPn(2)) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Multiple C statements can be included in the code area of a word,
|
||||
but care must be taken to generally avoid {}s.
|
||||
If you find you need nesting, a separate function is recommended.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
New variables can be declared in each word and are scoped to that word.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(MY_WORD, cell_t foo = n0; DROP; char *x = c0; DROP; \
|
||||
PUSH my_func(foo, x)) \
|
||||
</pre>
|
||||
|
||||
@ -18,6 +18,11 @@ handlers:
|
||||
upload: index.html
|
||||
secure: always
|
||||
|
||||
- url: /(.*).html
|
||||
static_files: \1.html
|
||||
upload: *.html
|
||||
secure: always
|
||||
|
||||
- url: /static
|
||||
static_dir: static
|
||||
secure: always
|
||||
|
||||
62
ueforth/site/classic.html
Normal file
62
ueforth/site/classic.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Classic EForth</title>
|
||||
<link rel="stylesheet" href="static/eforth.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Classic EForth</h1>
|
||||
|
||||
<div class="menu">
|
||||
<span><a href="ESP32forth.html">ESP32forth</a></span>
|
||||
<span><a href="linux.html">Linux</a></span>
|
||||
<span><a href="windows.html">Windows</a></span>
|
||||
<span><a href="internals.html">Internals</a></span>
|
||||
<span class="picked"><a href="classic.html">Classic</a></span>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
EForth is a delightfully minimalist approach to Forth originated by Bill Muench and Dr. C. H. Ting.
|
||||
</p>
|
||||
|
||||
<h2>Classic ESP32forth</h2>
|
||||
|
||||
<p>
|
||||
ESP32forth - Version 6.3 for NodeMCU ESP32S - Tweaked for the Web
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="static/ESP32forth-6.3.0.ino">ESP32forth-6.3.0.ino</a>
|
||||
</ul>
|
||||
|
||||
<h3>Classic EForth Quirks</h3>
|
||||
|
||||
<p>
|
||||
EForth exclusively uses <code>FOR..NEXT</code> in favor of <code>DO..LOOP</code>.
|
||||
<a href="https://github.com/TG9541/stm8ef/wiki/eForth-FOR-..-NEXT">Details</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This construct has the odd property that it iterates one "extra" time for zero.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
: FOO 10 FOR R@ . NEXT ; FOO
|
||||
10 9 8 7 6 5 4 3 2 1 0 ok
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To permit a more ordinary loop the <code>AFT</code> word is used in the sequence
|
||||
<code>FOR..AFT..THEN..NEXT</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
: FOO 10 FOR ( 1st time only ) AFT R@ . THEN NEXT ; FOO
|
||||
9 8 7 6 5 4 3 2 1 0 ok
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The even more enigmatic <code>FOR..WHILE..NEXT..ELSE..THEN</code>
|
||||
is used in place of <code>DO..LEAVE..LOOP</code>.
|
||||
It allows a while condition to early out of a counted loop.
|
||||
</p>
|
||||
@ -2,761 +2,21 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>EForth</title>
|
||||
<style>
|
||||
body {
|
||||
max-width: 800px;
|
||||
}
|
||||
h1 {
|
||||
border-top: 3px solid #777;
|
||||
background-color: #111;
|
||||
color: #eee;
|
||||
padding: 10px;
|
||||
margin-top: 0;
|
||||
}
|
||||
h2 {
|
||||
border-top: 2px solid #777;
|
||||
background-color: #ccc;
|
||||
padding: 10px;
|
||||
}
|
||||
h3 {
|
||||
border-top: 1px solid #777;
|
||||
background-color: #eee;
|
||||
padding: 10px;
|
||||
}
|
||||
h5 {
|
||||
margin: 2px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="static/eforth.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>EForth</h1>
|
||||
<script>
|
||||
window.location.replace('./ESP32forth.html');
|
||||
</script>
|
||||
<div class="menu">
|
||||
<span><a href="ESP32forth.html">ESP32forth</a></span>
|
||||
<span><a href="linux.html">Linux</a></span>
|
||||
<span><a href="windows.html">Windows</a></span>
|
||||
<span><a href="internals.html">Internals</a></span>
|
||||
<span><a href="classic.html">Classic</a></span>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
EForth is a delightfully minimalist approach to Forth originated by Bill Muench and Dr. C. H. Ting.
|
||||
</p>
|
||||
|
||||
<h2>Downloads</h2>
|
||||
|
||||
<h3>µEforth</h3>
|
||||
|
||||
<p>
|
||||
A reduced cross-platform EForth version
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="static/ESP32forth-{{VERSION}}.zip">ESP32forth-{{VERSION}}.zip</a>
|
||||
- <b>ESP32forth</b> Source Code <b>← SVFIG & Forth2020 folks start here!</b>
|
||||
<ul>
|
||||
<li><b>ESP32 Dev Module or similar (may work better with your particular board)</b>
|
||||
<ul>
|
||||
<li><b>Board:</b> ESP32 Dev Module</li>
|
||||
<li><b>Partition Scheme:</b> No OTA (2M APP, 2M SPIFFS) <b>← Non-default</b></li>
|
||||
<small>
|
||||
<li><b>Upload Speed:</b> 921600</li>
|
||||
<li><b>CPU Frequency:</b> 240MHz</li>
|
||||
<li><b>Flash Frequency:</b> 80MHz</li>
|
||||
<li><b>Flash Mode:</b> QIO</li>
|
||||
<li><b>Flash Size:</b> 4MB</li>
|
||||
<li><b>Core Debug Level:</b> None</li>
|
||||
<li><b>PSRAM:</b> Disabled</li>
|
||||
</small>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>ESP32-CAM</b>
|
||||
<ul>
|
||||
<li><b>Board:</b> AI Thinker ESP32-CAM</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="static/uEf32-{{VERSION}}.exe">uEf32-{{VERSION}}.exe</a> - Window 32-bit EXE µEforth</li>
|
||||
<li><a href="static/uEf64-{{VERSION}}.exe">uEf64-{{VERSION}}.exe</a> - Window 64-bit EXE µEforth</li>
|
||||
<li><a href="static/ueforth-{{VERSION}}.linux">ueforth-{{VERSION}}.linux</a> - Linux 64-bit Executable µEforth</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/flagxor/eforth" target="_blank">http://github.com/flagxor/eforth</a>
|
||||
- Complete Source Code (under ueforth)
|
||||
</p>
|
||||
|
||||
<h2>µEforth</h2>
|
||||
|
||||
<h3>µEforth Specific Words</h3>
|
||||
|
||||
<h5>Null Terminated Strings</h5>
|
||||
<p>
|
||||
As null terminated strings are used by virtually all platforms,
|
||||
their use is supported in Forth by way of several non-standard
|
||||
words with the convention of using Z/z to refer to such strings
|
||||
in names and stack comments.
|
||||
</p>
|
||||
<pre>
|
||||
Z" ( "string" -- z ) Creates a null terminated string on the heap
|
||||
Z>S ( z -- a n ) Convert a null terminated string to a counted string
|
||||
S>Z ( a n -- z ) Conver a counted string string to null terminated (copies string to heap)
|
||||
</pre>
|
||||
|
||||
<h5>Raw Strings</h5>
|
||||
<p>
|
||||
Raw strings are provided better support using a string
|
||||
for the duration of the current command, without consuming heap memory.
|
||||
</p>
|
||||
<pre>
|
||||
R" ( "string" -- a n ) Creates a temporary counted string
|
||||
R| ( string| -- a n ) Creates a temporary counted string ending with |
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
DUMP ( a n -- ) Dump a memory region
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
VARIABLE ECHO -- Determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h5>Vocabularies</h5>
|
||||
<p>
|
||||
µEforth uses a hybrid of Forth-79 and Forth-83 style vocabularies.
|
||||
By default vocabularies chain to the vocabulary in which they were defined,
|
||||
as in Forth-79. However, like Forth-83, <code>ALSO</code>
|
||||
can be used to add vocabularies to a vocabulary stack of which
|
||||
<code>CONTEXT @</code> is the first item.
|
||||
The word <code>ONLY</code> clears the vocabulary stack, but as there is
|
||||
no separate ONLY vocabulary, it also sets <code>CONTEXT</code>
|
||||
to the <code>FORTH</code> vocabulary.
|
||||
The word <code>SEALED</code> modifies the most recently defined vocabulary
|
||||
such that it does not chain. Note, this must be done before words are added to it.
|
||||
</p>
|
||||
<pre>
|
||||
VOCABULARY ( "name" ) Create a vocabulary with the current vocabulary as parent
|
||||
FORTH ( -- ) Make the FORTH vocabulary the context vocabulary
|
||||
DEFINITIONS ( -- ) Make the context vocabulary the current vocabulary
|
||||
VLIST ( -- ) List the words in the context vocabulary (not chains)
|
||||
WORDS ( -- ) List the words in the context vocabulary (including chains)
|
||||
TRANSFER ( "name" ) Move a word from its current dictionary to the current vocabulary
|
||||
Useful for "hiding" built-in words
|
||||
ALSO ( -- ) Duplicate the vocabulary at the top of the vocabulary stack
|
||||
ONLY ( -- ) Reset context stack to one item, the FORTH dictionary
|
||||
Non-standard, as there's no distinct ONLY vocabulary
|
||||
ORDER ( -- ) Print the vocabulary search order
|
||||
SEALED ( -- ) Alter the last vocabulary defined so it doesn't chain
|
||||
</pre>
|
||||
|
||||
<h5>Blocks</h5>
|
||||
<pre>
|
||||
USE ( "name" -- ) Use "name" as the blockfile, e.g. USE /spiffs/foo
|
||||
OPEN-BLOCKS ( a n -- ) Open a file as the block file
|
||||
LOAD ( n -- ) Evaluate a block
|
||||
THRU ( a b -- ) Load blocks a thru b
|
||||
LIST ( n -- ) List a block
|
||||
BLOCK ( n -- a ) Get a 1024 byte block
|
||||
BUFFER ( n -- a ) Get a 1024 byte block without regard to old contents
|
||||
UPDATE ( -- ) Mark the last block modified
|
||||
FLUSH ( -- ) Save and empty all buffers
|
||||
EMPTY-BUFFERS ( -- ) Empty all buffers
|
||||
SAVE-BUFFERS ( -- ) Save all buffers
|
||||
SCR ( -- a ) Pointer to last listed block
|
||||
</pre>
|
||||
|
||||
<h5>Block Editor</h5>
|
||||
These words are available inside the <code>EDITOR</code> vocabulary.
|
||||
<pre>
|
||||
WIPE ( -- ) Blank out the current block
|
||||
L ( -- ) List the current block
|
||||
D ( n -- ) Delete a line in the current block
|
||||
E ( n -- ) Clear a line in the current block
|
||||
R ( n "text" -- ) Replace a line in the current block
|
||||
A ( n "text" -- ) Add (insert) a line in the current block
|
||||
P ( -- ) Move to the previous block
|
||||
N ( -- ) Move to the next block
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
ECHO ( -- a ) -- Address of flag that determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h3>ESP32 Arduino</h3>
|
||||
|
||||
<h4>ESP32 Arduino Opcodes</h4>
|
||||
|
||||
<p>
|
||||
Because Arduino builds a statically linked image for flashing into ESP32 devices,
|
||||
all C function bindings need to be explicitly added.
|
||||
This is the current collection.
|
||||
Typically to reduce confusion, function names have be preserved even through verbose.
|
||||
In popular cases a shorted higher level name is provided.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/arduino/arduino.template.ino">arduino.template.ino</a>.
|
||||
</p>
|
||||
|
||||
<h5>Allocation</h5>
|
||||
These words are inside the <code>internals</code> vocabulary.
|
||||
<pre>
|
||||
MALLOC ( n -- a | 0 ) System malloc
|
||||
SYSFREE ( a -- ) System free
|
||||
REALLOC ( a n -- a | 0 ) System realloc
|
||||
</pre>
|
||||
|
||||
<h5>Serial</h5>
|
||||
These words are inside the <code>Serial</code> vocabulary.
|
||||
<pre>
|
||||
Serial.begin ( baud -- ) Start serial port
|
||||
Serial.end ( -- ) End serial port
|
||||
Serial.available ( -- f ) Is serial data available
|
||||
Serial.readBytes ( a n -- n ) Read serial bytes, return number gotten
|
||||
Serial.write ( a n -- n ) Write serial bytes
|
||||
Serial.flush ( -- ) Flush serial buffer
|
||||
</pre>
|
||||
|
||||
<h5>Serial Bluetooth</h5>
|
||||
These words are inside the <code>bluetooth</code> vocabulary.
|
||||
<pre>
|
||||
SerialBT.new ( -- bt ) Allocate new BT object
|
||||
SerialBT.delete ( bt -- ) Free BT object
|
||||
SerialBT.begin ( localname ismaster bt -- f )
|
||||
SerialBT.end ( bt -- )
|
||||
SerialBT.available ( bt -- f )
|
||||
SerialBT.readBytes ( a n bt -- n )
|
||||
SerialBT.write ( a n bt -- n )
|
||||
SerialBT.flush ( bt -- )
|
||||
SerialBT.hasClient ( bt -- f )
|
||||
SerialBT.enableSSP ( bt -- )
|
||||
SerialBT.setPin ( z bt -- f )
|
||||
SerialBT.unpairDevice ( addr bt -- f )
|
||||
SerialBT.connect ( remotename bt -- f )
|
||||
SerialBT.connectAddr ( addr bt -- f )
|
||||
SerialBT.disconnect ( bt -- f )
|
||||
SerialBT.connected ( timeout bt -- f )
|
||||
SerialBT.isReady ( checkMaster timeout -- f ) Default checkMaster=false, timeout=0
|
||||
</pre>
|
||||
|
||||
<h5>Bluetooth</h5>
|
||||
These words are inside the <code>bluetooth</code> vocabulary.
|
||||
<pre>
|
||||
esp_bt_dev_get_address ( -- a ) addr of 6 byte mac address
|
||||
</pre>
|
||||
|
||||
<h5>GPIO</h5>
|
||||
<pre>
|
||||
pinMode ( pin mode -- ) Set GPIO pin mode
|
||||
digitalWrite ( pin value -- ) Set GPIO pin state
|
||||
analogRead ( pin -- n ) Analog read from 0-4095
|
||||
</pre>
|
||||
|
||||
<h5>ledc</h5>
|
||||
These words are inside the <code>ledc</code> vocabulary.
|
||||
<pre>
|
||||
ledcSetup ( channel freq resolution -- freq )
|
||||
ledcAttachPin ( pin channel -- )
|
||||
ledcDetachPin ( pin -- )
|
||||
ledcRead ( channel -- n )
|
||||
ledcReadFreq ( channel -- freq ) Get frequency (x 1,000,000)
|
||||
ledcWrite ( channel duty -- )
|
||||
ledcWriteTone ( channel freq ) Write tone frequency (x 1000)
|
||||
ledcWriteNote ( channel note octave -- freq )
|
||||
</pre>
|
||||
|
||||
<h5>Short GPIO Names</h5>
|
||||
<pre>
|
||||
pin ( value pin# -- ) Set GPIO pin value
|
||||
adc ( pin# -- n ) Analog read pin, result 0-1023
|
||||
</pre>
|
||||
|
||||
<h5>System</h5>
|
||||
<pre>
|
||||
MS ( n -- )
|
||||
TERMINATE ( n -- ) Call system exit
|
||||
</pre>
|
||||
|
||||
<h5>Files</h5>
|
||||
<pre>
|
||||
R/O ( -- mode )
|
||||
R/W ( -- mode )
|
||||
W/O ( -- mode )
|
||||
BIN ( mode -- mode )
|
||||
CLOSE-FILE ( fh -- ior )
|
||||
OPEN-FILE ( a n mode -- fh ior )
|
||||
CREATE-FILE ( a n mode -- fh ior )
|
||||
DELETE-FILE ( a n -- ior )
|
||||
WRITE-FILE ( a n fh -- ior )
|
||||
READ-FILE ( a n fh -- n ior )
|
||||
FILE-POSITION ( fh -- n ior )
|
||||
REPOSITION-FILE ( n fh -- ior )
|
||||
FILE-SIZE ( fh -- n ior )
|
||||
</pre>
|
||||
|
||||
<h5>WiFi</h5>
|
||||
These words are inside the <code>WiFi</code> vocabulary.
|
||||
<pre>
|
||||
WiFi.config ( ip dns gateway subnet -- ) Packaged a.b.c.d little-endian
|
||||
Wifi.begin ( ssid-z password-z -- )
|
||||
Wifi.disconnect ( -- )
|
||||
WiFi.status ( -- n )
|
||||
WiFi.macAddress ( a -- )
|
||||
WiFi.localIP ( -- ip )
|
||||
WiFi.mode ( mode -- ) WIFI_MODE_NULL WIFI_MODE_STA WIFI_MODE_AP WIFI_MODE_APSTA
|
||||
WiFi.setTxPower ( powerx4 -- ) Set power x4
|
||||
WiFi.getTxPower ( -- powerx4 ) Get power x4
|
||||
</pre>
|
||||
|
||||
<h5>mDNS</h5>
|
||||
<pre>
|
||||
MDNS.begin ( name-z -- ) Start multicast dns
|
||||
</pre>
|
||||
|
||||
<h5>SPIFFS</h5>
|
||||
These words are inside the <code>SPIFFS</code> vocabulary.
|
||||
<pre>
|
||||
SPIFFS.begin ( format-on-fail path-z max-files -- f )
|
||||
SPIFFS.end ( -- )
|
||||
SPIFFS.format ( -- f )
|
||||
SPIFFS.totalBytes ( -- n )
|
||||
SPIFFS.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h5>WebServer</h5>
|
||||
These words are inside the <code>WebServer</code> vocabulary.
|
||||
<pre>
|
||||
WebServer.new ( port -- ws ) Allocate new webserver object
|
||||
WebServer.delete ( ws -- ) Delete webserver object
|
||||
WebServer.begin ( port ws -- )
|
||||
WebServer.stop ( ws -- )
|
||||
WebServer.on ( path-z xt ws -- ) Set up a web path handle callback
|
||||
WebServer.handleClient ( ws -- ) Handle one client request
|
||||
WebServer.hasArg ( z ws -- f ) By name
|
||||
WebServer.arg ( z ws -- z ) By name
|
||||
WebServer.argi ( n ws -- z ) By index
|
||||
WebServer.argName ( n ws -- z) By index
|
||||
WebServer.args ( ws -- n ) Number of args
|
||||
WebServer.setContentLength ( n ws -- )
|
||||
WebServer.sendHeader ( name-z value-z fist ws -- )
|
||||
WebServer.send ( code mimetype data ws -- )
|
||||
WebServer.sendContent ( z ws -- )
|
||||
WebServer.method ( ws -- n ) GET / POST etc.
|
||||
</pre>
|
||||
|
||||
<h5>Wire</h5>
|
||||
These words are inside the <code>Wire</code> vocabulary.
|
||||
<pre>
|
||||
Wire.begin ( -- f )
|
||||
Wire.setPins ( sda scl -- f )
|
||||
Wire.setClock ( frequency -- )
|
||||
Wire.getClock ( -- frequency )
|
||||
Wire.setTimeout ( ms -- ) Default is 50ms
|
||||
Wire.getTimeout ( -- ms )
|
||||
Wire.lastError ( -- n )
|
||||
Wire.getErrorText ( n -- z )
|
||||
Wire.beginTransmission ( n -- )
|
||||
Wire.endTransmission ( sendstop -- f )
|
||||
Wire.requestFrom ( address quantity sendstop -- n )
|
||||
Wire.writeTransmission ( addr a n sendstop -- err )
|
||||
Wire.readTransmission ( addr a n sendstop acount -- err )
|
||||
Wire.write ( a n -- n )
|
||||
Wire.available ( -- f )
|
||||
Wire.read ( -- ch )
|
||||
Wire.peek ( -- ch )
|
||||
Wire.busy ( -- f )
|
||||
Wire.flush ( -- )
|
||||
</pre>
|
||||
|
||||
<h5>Camera</h5>
|
||||
These words are inside the <code>camera</code> vocabulary.
|
||||
<pre>
|
||||
esp_camera_init ( config -- f )
|
||||
esp_camera_deinit ( -- f )
|
||||
esp_camera_fb_get ( -- fb )
|
||||
esp_camera_fb_return ( fb -- )
|
||||
esp_camera_sensor_get ( -- sensor )
|
||||
</pre>
|
||||
|
||||
<h5>SD_MMC</h5>
|
||||
These words are inside the <code>SD_MMC</code> vocabulary.
|
||||
<pre>
|
||||
SD_MMC.begin ( mount mode1bit ) default mode1bit=false
|
||||
SD_MMC.end ( -- )
|
||||
SD_MMC.cardType ( -- n )
|
||||
SD_MMC.totalBytes ( -- n )
|
||||
SD_MMC.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h4 id="webui">ESP32 WebUI</h4>
|
||||
|
||||
<p>
|
||||
A terminal over the web can be activated.
|
||||
Contact at port printed or via mDNS <a href="http://ueforth/">http://ueforth/</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
webui ( network-z password-z -- )
|
||||
</pre>
|
||||
|
||||
<p>Usage:</p>
|
||||
|
||||
<pre>
|
||||
z" NETWORK-NAME" z" PASSWORD" webui
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/arduino/arduino_server.fs">arduino_server.fs</a>.
|
||||
</p>
|
||||
|
||||
<h4 id="autoexec">Autoexec.fs</h4>
|
||||
|
||||
<p>
|
||||
The system will automatically attempt to mount SPIFFS filesystem at <code>/spiffs</code>.
|
||||
It will then at start attempt to load <code>/spiffs/autoexec.fs</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One way this feature can be used to configure the Web UI to start by default.
|
||||
When doing this, be sure to test your Web UI settings work well first.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
r| z" NETWORK-NAME" z" PASSWORD" webui | s" /spiffs/autoexec.fs" dump-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To remove a previously configured <code>autoexec.fs</code> you will need
|
||||
to be able to reboot in a mode with Forth. One way to do this is to search
|
||||
for the line in the .ino file that refers to <code>autoexec.fs</code>
|
||||
and replace it with a different name. Then run the following:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s" /spiffs/autoexec.fs" delete-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/arduino/autoboot.fs">autoboot.fs</a>.
|
||||
</p>
|
||||
|
||||
<h4 id="adding_words">Adding Words</h4>
|
||||
|
||||
<p>
|
||||
Adding words based on C functions can be done by editing the source code.
|
||||
For ESP32 Arduino <code>arduino.template.ino</code> is the appropriate place.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Because of the use of <a href="https://en.wikipedia.org/wiki/X_Macro">X-Macros</a> words can be
|
||||
added in as little as one line. Locate the macro called <code>PLATFORM_OPCODE_LIST</code>
|
||||
and add your words there.
|
||||
</p>
|
||||
|
||||
<p>NOTE: Be careful to end each line with a \ so the macros will chain correctly.</p>
|
||||
|
||||
<p>
|
||||
To add a word containing only letters, numbers, and underscore you can use <code>Y</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(MY_WORD123, c_function_to_call()) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If your word name contains other characters, instead use <code>X</code>.
|
||||
You will need to make up an alternate name for the middle parameter.
|
||||
It must contain only letters, numbers, and underscore.
|
||||
The name is not used anywhere else, but must be unique.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
X("myword!", MY_WORD_BANG, c_function_to_call()) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Values from the data stack can be accessed via
|
||||
the variables <code>tos</code> (Top of Stack) and
|
||||
<code>sp</code> (Pointer to the rest of the stack).
|
||||
The stack has the data type <code>cell_t</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can push a value of any type to the stack with the macro <code>PUSH</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(MY_WORD, PUSH calculate_magic_value()) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To simplify calling C functions, you can also refer to elements on the stack
|
||||
with the types positional names:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
n10 n9 n8 n7 n6 n5 n4 n3 n2 n1 n0 - Access stack as cell_t integer values
|
||||
c4 c3 c2 c1 c0 - Access stack as char* values
|
||||
b4 b3 b2 b1 b0 - Access stack as uint8_t* byte values
|
||||
a4 a3 a2 a1 a0 - Access stack as void* values
|
||||
|
||||
Examples:
|
||||
void send_message(const char *message, int code);
|
||||
...
|
||||
X("send-message", SEND_MESSAGE, send_message(c1, n0)) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You can always replace the top item on the stack with <code>SET</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(DECODE, SET decode_func(n0)) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You can drop elements from the stack with <code>DROP</code>
|
||||
or <code>DROPn(number)</code>.
|
||||
You can nip elements from below top of the stack with <code>NIP</code>
|
||||
or <code>NIPn(number)</code>.
|
||||
Be aware that like <code>PUSH</code> this will cause stack indices to change.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int my_cool_function(char *foo, int bar, uint8_t *baz);
|
||||
...
|
||||
Y(MY_FUNC, n0 = my_cool_function(c2, n1, b0); NIPn(2)) \
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Multiple C statements can be included in the code area of a word,
|
||||
but care must be taken to generally avoid {}s.
|
||||
If you find you need nesting, a separate function is recommended.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
New variables can be declared in each word and are scoped to that word.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
Y(MY_WORD, cell_t foo = n0; DROP; char *x = c0; DROP; \
|
||||
PUSH my_func(foo, x)) \
|
||||
</pre>
|
||||
|
||||
<h3>Windows</h3>
|
||||
|
||||
<h4>Windows Opcodes</h4>
|
||||
|
||||
<p>
|
||||
The wealth of Windows .DLL and system functionality can be
|
||||
accessed via the dynamic loading interface.
|
||||
A handle to a library is obtained with <code>LOADLIBRARYA</code>,
|
||||
and then individual symbols are accessed with <code>GETPROCADDRESS</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
LOADLIBRARYA ( dllname-z -- module )
|
||||
GETPROCADDRESS ( module name-z -- fn )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
And assembly version of <code>*/MOD</code> is provided to allow the EXE to build without
|
||||
including MSVCRT.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/windows/windows_main.c">windows_main.c</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Native functions all called with CALL(n) (see Windows & Linux Calling below).
|
||||
</p>
|
||||
|
||||
<h4>Windows Imports</h4>
|
||||
|
||||
<p>
|
||||
Various Win32 calls are imported in
|
||||
<a href="https://github.com/flagxor/eforth/blob/main/ueforth/windows/windows.fs">windows.fs</a>.
|
||||
In addition, a terminal that responds to ANSI escape codes is created and connected to
|
||||
<code>TYPE</code> and <code>KEY</code>.
|
||||
</p>
|
||||
|
||||
<h3>Linux</h3>
|
||||
|
||||
<h4>Linux Opcodes</h4>
|
||||
|
||||
<p>
|
||||
Linux libraries and the operating system can be accessed via the use
|
||||
of the <code>DLSYM</code> word. Functions can be requested by name from
|
||||
particular modules. As the dynamic linking module is already loaded initially,
|
||||
a 0 for the module allows the library loading function (<code>dlopen</code>)
|
||||
to be loaded from Forth.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
DLSYM ( module name-z -- fn )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/posix/posix_main.c">posix_main.c</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Native functions all called with CALL(n) (see Windows & Linux Calling below).
|
||||
</p>
|
||||
|
||||
<h4>Linux Imports</h4>
|
||||
|
||||
<p>
|
||||
Various Linux calls including Xlib are imported in
|
||||
<a href="https://github.com/flagxor/eforth/blob/main/ueforth/posix/posix.fs">posix.fs</a> and
|
||||
<a href="https://github.com/flagxor/eforth/blob/main/ueforth/posix/xlib.fs">xlib.fs</a>.
|
||||
In addition, <code>TYPE</code> and <code>KEY</code> are connected to
|
||||
<code>stdin</code> and <code>stdout</code>.
|
||||
</p>
|
||||
|
||||
<h3>Windows & Linux Calling</h3>
|
||||
|
||||
<p>
|
||||
As unfortunately both Windows and Linux have system and library calls with
|
||||
as many as 10 parameters (for example <code>XCreateImage</code>),
|
||||
a collection of calling thunks is required.
|
||||
A single varidic thunk would be ideal, but is hard to do without per platform
|
||||
assembly language.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
CALL0 ( fn -- n )
|
||||
CALL1 ( n fn -- n )
|
||||
CALL2 ( n n fn -- n )
|
||||
CALL3 ( n n n fn -- n )
|
||||
CALL4 ( n n n n fn -- n )
|
||||
CALL5 ( n n n n n fn -- n )
|
||||
CALL6 ( n n n n n n fn -- n )
|
||||
CALL7 ( n n n n n n n fn -- n )
|
||||
CALL7 ( n n n n n n n n fn -- n )
|
||||
CALL9 ( n n n n n n n n n fn -- n )
|
||||
CALL10 ( n n n n n n n n n n fn -- n )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/calling.h">calling.h</a>.
|
||||
</p>
|
||||
|
||||
<h3>Web</h3>
|
||||
|
||||
<font style="font-size: 18pt; color: #C00;">Work in Progress - Coming Soon</font>
|
||||
|
||||
<h3>µEforth Internals</h3>
|
||||
|
||||
<p>
|
||||
µEforth (micro-Eforth) simplifies EForth even futher, by building just enough
|
||||
of the core of the system in C to allow the rest to be be built in proper Forth.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A handful of "tricky" words that involve internal loops or many steps are built in their own
|
||||
functions:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
FIND ( a n -- xt | 0 )
|
||||
PARSE ( ch -- a n )
|
||||
S>NUMBER? ( a n -- n f | 0 )
|
||||
CREATE ( "name" -- )
|
||||
EVALUATE1 ( -- )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This includes <code>EVALUATE1</code> which parses a single word and
|
||||
interprets or compiles it (reusing <code>PARSE</code>,
|
||||
<code>FIND</code>, and <code>S>NUMBER?</code>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/core.h">core.h</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A few global variables connect parsing and compilation state between
|
||||
C and Forth (by way of a memory region accessed via <code>'SYS</code>):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
'TIB --- Pointer to the Translation Input Buffer
|
||||
#TIB --- Length of the Translation Input Buffer
|
||||
>IN --- Number of characters consumed from TIB
|
||||
|
||||
BASE --- Numeric base for printing and parsing
|
||||
|
||||
STATE --- State of compiling, -1 for compiling, 0 for interpreting
|
||||
CURRENT --- Pointer to pointer to last word of current vocabulary
|
||||
CONTEXT --- Pointer to pointer to last word of context vocabulary
|
||||
|
||||
'NOTFOUND --- Execution token of a handler to call on word not found
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Error handling is routed via a deferred callback in <code>'NOTFOUND</code>
|
||||
used when a word is absent from the dictionary.
|
||||
This is eventually directed to an error routing that prints
|
||||
a proper error, once I/O and exceptions are available.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://en.wikipedia.org/wiki/X_Macro">X-Macros</a>
|
||||
are then used to build up a small set of core opcodes defined in 1-3 lines each:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
0= 0< + U/MOD */MOD AND OR XOR
|
||||
DUP SWAP OVER DROP @ L@ C@ ! L! C!
|
||||
SP@ SP! RP@ RP! >R R> R@ : ; EXIT
|
||||
EXECUTE BRANCH 0BRANCH DONEXT DOLIT
|
||||
ALITERAL CELL DOES> IMMEDIATE 'SYS
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/opcodes.h">opcodes.h</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I/O and access to systems outside Forth are connected via a few per platform words.
|
||||
Typically this set of words should be minimal, while still allowing relevant parts
|
||||
of the host system to be available to Forth.
|
||||
</p>
|
||||
|
||||
<h2>Classic esp32Forth</h2>
|
||||
|
||||
<p>
|
||||
esp32Forth - Version 6.3 for NodeMCU ESP32S - Tweaked for the Web
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="static/espforth.ino">espforth.ino</a>
|
||||
</ul>
|
||||
|
||||
<h3>Classic EForth Quirks</h3>
|
||||
|
||||
<p>
|
||||
EForth uses <code>FOR..NEXT</code> in favor of <code>DO..LOOP</code>.
|
||||
<a href="https://github.com/TG9541/stm8ef/wiki/eForth-FOR-..-NEXT">Details</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This construct has the odd property that it iterates one "extra" time for zero.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
: FOO 10 FOR R@ . NEXT ; FOO
|
||||
10 9 8 7 6 5 4 3 2 1 0 ok
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To permit a more ordinary loop the <code>AFT</code> word is used in the sequence
|
||||
<code>FOR..AFT..THEN..NEXT</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
: FOO 10 FOR ( 1st time only ) AFT R@ . THEN NEXT ; FOO
|
||||
9 8 7 6 5 4 3 2 1 0 ok
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The even more enigmatic <code>FOR..WHILE..NEXT..ELSE..THEN</code>
|
||||
is used in place of <code>DO..LEAVE..LOOP</code>.
|
||||
It allows a while condition to early out of a counted loop.
|
||||
Choose you platform above.
|
||||
</p>
|
||||
|
||||
94
ueforth/site/internals.html
Normal file
94
ueforth/site/internals.html
Normal file
@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ESP32forth</title>
|
||||
<link rel="stylesheet" href="static/eforth.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>µEforth Internals</h1>
|
||||
|
||||
<div class="menu">
|
||||
<span><a href="ESP32forth.html">ESP32forth</a></span>
|
||||
<span><a href="linux.html">Linux</a></span>
|
||||
<span><a href="windows.html">Windows</a></span>
|
||||
<span class="picked"><a href="internals.html">Internals</a></span>
|
||||
<span><a href="classic.html">Classic</a></span>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
µEforth (micro-Eforth) simplifies EForth even futher, by building just enough
|
||||
of the core of the system in C to allow the rest to be be built in proper Forth.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A handful of "tricky" words that involve internal loops or many steps are built in their own
|
||||
functions:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
FIND ( a n -- xt | 0 )
|
||||
PARSE ( ch -- a n )
|
||||
S>NUMBER? ( a n -- n f | 0 )
|
||||
CREATE ( "name" -- )
|
||||
EVALUATE1 ( -- )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This includes <code>EVALUATE1</code> which parses a single word and
|
||||
interprets or compiles it (reusing <code>PARSE</code>,
|
||||
<code>FIND</code>, and <code>S>NUMBER?</code>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/core.h">core.h</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A few global variables connect parsing and compilation state between
|
||||
C and Forth (by way of a memory region accessed via <code>'SYS</code>):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
'TIB --- Pointer to the Translation Input Buffer
|
||||
#TIB --- Length of the Translation Input Buffer
|
||||
>IN --- Number of characters consumed from TIB
|
||||
|
||||
BASE --- Numeric base for printing and parsing
|
||||
|
||||
STATE --- State of compiling, -1 for compiling, 0 for interpreting
|
||||
CURRENT --- Pointer to pointer to last word of current vocabulary
|
||||
CONTEXT --- Pointer to pointer to last word of context vocabulary
|
||||
|
||||
'NOTFOUND --- Execution token of a handler to call on word not found
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Error handling is routed via a deferred callback in <code>'NOTFOUND</code>
|
||||
used when a word is absent from the dictionary.
|
||||
This is eventually directed to an error routing that prints
|
||||
a proper error, once I/O and exceptions are available.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://en.wikipedia.org/wiki/X_Macro">X-Macros</a>
|
||||
are then used to build up a small set of core opcodes defined in 1-3 lines each:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
0= 0< + U/MOD */MOD AND OR XOR
|
||||
DUP SWAP OVER DROP @ L@ C@ ! L! C!
|
||||
SP@ SP! RP@ RP! >R R> R@ : ; EXIT
|
||||
EXECUTE BRANCH 0BRANCH DONEXT DOLIT
|
||||
ALITERAL CELL DOES> IMMEDIATE 'SYS
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/opcodes.h">opcodes.h</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I/O and access to systems outside Forth are connected via a few per platform words.
|
||||
Typically this set of words should be minimal, while still allowing relevant parts
|
||||
of the host system to be available to Forth.
|
||||
</p>
|
||||
|
||||
187
ueforth/site/linux.html
Normal file
187
ueforth/site/linux.html
Normal file
@ -0,0 +1,187 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Linux</title>
|
||||
<link rel="stylesheet" href="static/eforth.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>µEforth Linux</h1>
|
||||
|
||||
<div class="menu">
|
||||
<span><a href="ESP32forth.html">ESP32forth</a></span>
|
||||
<span class="picked"><a href="linux.html">Linux</a></span>
|
||||
<span><a href="windows.html">Windows</a></span>
|
||||
<span><a href="internals.html">Internals</a></span>
|
||||
<span><a href="classic.html">Classic</a></span>
|
||||
</div>
|
||||
|
||||
<h2>Download</h2>
|
||||
|
||||
<p>
|
||||
<a href="static/ueforth-{{VERSION}}.linux">ueforth-{{VERSION}}.linux</a>
|
||||
- Linux 64-bit Executable µEforth
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/flagxor/eforth" target="_blank">http://github.com/flagxor/eforth</a>
|
||||
- Complete Source Code (under ueforth)
|
||||
</p>
|
||||
|
||||
<h2>µEforth</h2>
|
||||
|
||||
<h3>µEforth Specific Words</h3>
|
||||
|
||||
<h5>Null Terminated Strings</h5>
|
||||
<p>
|
||||
As null terminated strings are used by virtually all platforms,
|
||||
their use is supported in Forth by way of several non-standard
|
||||
words with the convention of using Z/z to refer to such strings
|
||||
in names and stack comments.
|
||||
</p>
|
||||
<pre>
|
||||
Z" ( "string" -- z ) Creates a null terminated string on the heap
|
||||
Z>S ( z -- a n ) Convert a null terminated string to a counted string
|
||||
S>Z ( a n -- z ) Conver a counted string string to null terminated (copies string to heap)
|
||||
</pre>
|
||||
|
||||
<h5>Raw Strings</h5>
|
||||
<p>
|
||||
Raw strings are provided better support using a string
|
||||
for the duration of the current command, without consuming heap memory.
|
||||
</p>
|
||||
<pre>
|
||||
R" ( "string" -- a n ) Creates a temporary counted string
|
||||
R| ( string| -- a n ) Creates a temporary counted string ending with |
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
DUMP ( a n -- ) Dump a memory region
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
VARIABLE ECHO -- Determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h5>Vocabularies</h5>
|
||||
<p>
|
||||
µEforth uses a hybrid of Forth-79 and Forth-83 style vocabularies.
|
||||
By default vocabularies chain to the vocabulary in which they were defined,
|
||||
as in Forth-79. However, like Forth-83, <code>ALSO</code>
|
||||
can be used to add vocabularies to a vocabulary stack of which
|
||||
<code>CONTEXT @</code> is the first item.
|
||||
The word <code>ONLY</code> clears the vocabulary stack, but as there is
|
||||
no separate ONLY vocabulary, it also sets <code>CONTEXT</code>
|
||||
to the <code>FORTH</code> vocabulary.
|
||||
The word <code>SEALED</code> modifies the most recently defined vocabulary
|
||||
such that it does not chain. Note, this must be done before words are added to it.
|
||||
</p>
|
||||
<pre>
|
||||
VOCABULARY ( "name" ) Create a vocabulary with the current vocabulary as parent
|
||||
FORTH ( -- ) Make the FORTH vocabulary the context vocabulary
|
||||
DEFINITIONS ( -- ) Make the context vocabulary the current vocabulary
|
||||
VLIST ( -- ) List the words in the context vocabulary (not chains)
|
||||
WORDS ( -- ) List the words in the context vocabulary (including chains)
|
||||
TRANSFER ( "name" ) Move a word from its current dictionary to the current vocabulary
|
||||
Useful for "hiding" built-in words
|
||||
ALSO ( -- ) Duplicate the vocabulary at the top of the vocabulary stack
|
||||
ONLY ( -- ) Reset context stack to one item, the FORTH dictionary
|
||||
Non-standard, as there's no distinct ONLY vocabulary
|
||||
ORDER ( -- ) Print the vocabulary search order
|
||||
SEALED ( -- ) Alter the last vocabulary defined so it doesn't chain
|
||||
</pre>
|
||||
|
||||
<h5>Blocks</h5>
|
||||
<pre>
|
||||
USE ( "name" -- ) Use "name" as the blockfile, e.g. USE /spiffs/foo
|
||||
OPEN-BLOCKS ( a n -- ) Open a file as the block file
|
||||
LOAD ( n -- ) Evaluate a block
|
||||
THRU ( a b -- ) Load blocks a thru b
|
||||
LIST ( n -- ) List a block
|
||||
BLOCK ( n -- a ) Get a 1024 byte block
|
||||
BUFFER ( n -- a ) Get a 1024 byte block without regard to old contents
|
||||
UPDATE ( -- ) Mark the last block modified
|
||||
FLUSH ( -- ) Save and empty all buffers
|
||||
EMPTY-BUFFERS ( -- ) Empty all buffers
|
||||
SAVE-BUFFERS ( -- ) Save all buffers
|
||||
SCR ( -- a ) Pointer to last listed block
|
||||
</pre>
|
||||
|
||||
<h5>Block Editor</h5>
|
||||
These words are available inside the <code>EDITOR</code> vocabulary.
|
||||
<pre>
|
||||
WIPE ( -- ) Blank out the current block
|
||||
L ( -- ) List the current block
|
||||
D ( n -- ) Delete a line in the current block
|
||||
E ( n -- ) Clear a line in the current block
|
||||
R ( n "text" -- ) Replace a line in the current block
|
||||
A ( n "text" -- ) Add (insert) a line in the current block
|
||||
P ( -- ) Move to the previous block
|
||||
N ( -- ) Move to the next block
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
ECHO ( -- a ) -- Address of flag that determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h3>Linux</h3>
|
||||
|
||||
<h4>Linux Opcodes</h4>
|
||||
|
||||
<p>
|
||||
Linux libraries and the operating system can be accessed via the use
|
||||
of the <code>DLSYM</code> word. Functions can be requested by name from
|
||||
particular modules. As the dynamic linking module is already loaded initially,
|
||||
a 0 for the module allows the library loading function (<code>dlopen</code>)
|
||||
to be loaded from Forth.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
DLSYM ( module name-z -- fn )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/posix/posix_main.c">posix_main.c</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Native functions all called with CALL(n) (see Windows & Linux Calling below).
|
||||
</p>
|
||||
|
||||
<h4>Linux Imports</h4>
|
||||
|
||||
<p>
|
||||
Various Linux calls including Xlib are imported in
|
||||
<a href="https://github.com/flagxor/eforth/blob/main/ueforth/posix/posix.fs">posix.fs</a> and
|
||||
<a href="https://github.com/flagxor/eforth/blob/main/ueforth/posix/xlib.fs">xlib.fs</a>.
|
||||
In addition, <code>TYPE</code> and <code>KEY</code> are connected to
|
||||
<code>stdin</code> and <code>stdout</code>.
|
||||
</p>
|
||||
|
||||
<h3>Windows & Linux Calling</h3>
|
||||
|
||||
<p>
|
||||
As unfortunately both Windows and Linux have system and library calls with
|
||||
as many as 10 parameters (for example <code>XCreateImage</code>),
|
||||
a collection of calling thunks is required.
|
||||
A single varidic thunk would be ideal, but is hard to do without per platform
|
||||
assembly language.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
CALL0 ( fn -- n )
|
||||
CALL1 ( n fn -- n )
|
||||
CALL2 ( n n fn -- n )
|
||||
CALL3 ( n n n fn -- n )
|
||||
CALL4 ( n n n n fn -- n )
|
||||
CALL5 ( n n n n n fn -- n )
|
||||
CALL6 ( n n n n n n fn -- n )
|
||||
CALL7 ( n n n n n n n fn -- n )
|
||||
CALL7 ( n n n n n n n n fn -- n )
|
||||
CALL9 ( n n n n n n n n n fn -- n )
|
||||
CALL10 ( n n n n n n n n n n fn -- n )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/calling.h">calling.h</a>.
|
||||
</p>
|
||||
67
ueforth/site/static/eforth.css
Normal file
67
ueforth/site/static/eforth.css
Normal file
@ -0,0 +1,67 @@
|
||||
body {
|
||||
max-width: 800px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
h1 {
|
||||
border-top: 3px solid #777;
|
||||
background-color: #111;
|
||||
color: #eee;
|
||||
padding: 10px;
|
||||
margin: 0px;
|
||||
}
|
||||
h2 {
|
||||
border-top: 2px solid #777;
|
||||
background-color: #ccc;
|
||||
padding: 10px;
|
||||
}
|
||||
h3 {
|
||||
border-top: 1px solid #777;
|
||||
background-color: #eee;
|
||||
padding: 10px;
|
||||
}
|
||||
h5 {
|
||||
margin: 2px;
|
||||
}
|
||||
a:link {
|
||||
color: #00c;
|
||||
}
|
||||
a:visited {
|
||||
color: #00c;
|
||||
}
|
||||
a:active {
|
||||
color: #0f0;
|
||||
}
|
||||
a:hover {
|
||||
color: #0f0;
|
||||
}
|
||||
.menu {
|
||||
background-color: #333;
|
||||
border-top: 3px solid #777;
|
||||
padding: 10px;
|
||||
}
|
||||
.menu span {
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
}
|
||||
.menu a:link {
|
||||
color: #fff;
|
||||
}
|
||||
.menu a:visited {
|
||||
color: #fff;
|
||||
}
|
||||
.menu a:active {
|
||||
color: #0f0;
|
||||
}
|
||||
.menu a:hover {
|
||||
color: #0f0;
|
||||
}
|
||||
.menu .picked {
|
||||
background-color: #070;
|
||||
}
|
||||
.menu .picked a:active {
|
||||
color: #fff;
|
||||
}
|
||||
.menu .picked a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
197
ueforth/site/windows.html
Normal file
197
ueforth/site/windows.html
Normal file
@ -0,0 +1,197 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>EForth</title>
|
||||
<link rel="stylesheet" href="static/eforth.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>µEforth Windows</h1>
|
||||
|
||||
<div class="menu">
|
||||
<span><a href="ESP32forth.html">ESP32forth</a></span>
|
||||
<span><a href="linux.html">Linux</a></span>
|
||||
<span class="picked"><a href="windows.html">Windows</a></span>
|
||||
<span><a href="internals.html">Internals</a></span>
|
||||
<span><a href="classic.html">Classic</a></span>
|
||||
</div>
|
||||
|
||||
<h2>Download</h2>
|
||||
|
||||
<p>
|
||||
<a href="static/uEf32-{{VERSION}}.exe">uEf32-{{VERSION}}.exe</a>
|
||||
- Window 32-bit EXE µEforth
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="static/uEf64-{{VERSION}}.exe">uEf64-{{VERSION}}.exe</a>
|
||||
- Window 64-bit EXE µEforth
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/flagxor/eforth" target="_blank">http://github.com/flagxor/eforth</a>
|
||||
- Complete Source Code (under ueforth)
|
||||
</p>
|
||||
|
||||
<h2>µEforth</h2>
|
||||
|
||||
<h3>µEforth Specific Words</h3>
|
||||
|
||||
<h5>Null Terminated Strings</h5>
|
||||
<p>
|
||||
As null terminated strings are used by virtually all platforms,
|
||||
their use is supported in Forth by way of several non-standard
|
||||
words with the convention of using Z/z to refer to such strings
|
||||
in names and stack comments.
|
||||
</p>
|
||||
<pre>
|
||||
Z" ( "string" -- z ) Creates a null terminated string on the heap
|
||||
Z>S ( z -- a n ) Convert a null terminated string to a counted string
|
||||
S>Z ( a n -- z ) Conver a counted string string to null terminated (copies string to heap)
|
||||
</pre>
|
||||
|
||||
<h5>Raw Strings</h5>
|
||||
<p>
|
||||
Raw strings are provided better support using a string
|
||||
for the duration of the current command, without consuming heap memory.
|
||||
</p>
|
||||
<pre>
|
||||
R" ( "string" -- a n ) Creates a temporary counted string
|
||||
R| ( string| -- a n ) Creates a temporary counted string ending with |
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
DUMP ( a n -- ) Dump a memory region
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
VARIABLE ECHO -- Determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h5>Vocabularies</h5>
|
||||
<p>
|
||||
µEforth uses a hybrid of Forth-79 and Forth-83 style vocabularies.
|
||||
By default vocabularies chain to the vocabulary in which they were defined,
|
||||
as in Forth-79. However, like Forth-83, <code>ALSO</code>
|
||||
can be used to add vocabularies to a vocabulary stack of which
|
||||
<code>CONTEXT @</code> is the first item.
|
||||
The word <code>ONLY</code> clears the vocabulary stack, but as there is
|
||||
no separate ONLY vocabulary, it also sets <code>CONTEXT</code>
|
||||
to the <code>FORTH</code> vocabulary.
|
||||
The word <code>SEALED</code> modifies the most recently defined vocabulary
|
||||
such that it does not chain. Note, this must be done before words are added to it.
|
||||
</p>
|
||||
<pre>
|
||||
VOCABULARY ( "name" ) Create a vocabulary with the current vocabulary as parent
|
||||
FORTH ( -- ) Make the FORTH vocabulary the context vocabulary
|
||||
DEFINITIONS ( -- ) Make the context vocabulary the current vocabulary
|
||||
VLIST ( -- ) List the words in the context vocabulary (not chains)
|
||||
WORDS ( -- ) List the words in the context vocabulary (including chains)
|
||||
TRANSFER ( "name" ) Move a word from its current dictionary to the current vocabulary
|
||||
Useful for "hiding" built-in words
|
||||
ALSO ( -- ) Duplicate the vocabulary at the top of the vocabulary stack
|
||||
ONLY ( -- ) Reset context stack to one item, the FORTH dictionary
|
||||
Non-standard, as there's no distinct ONLY vocabulary
|
||||
ORDER ( -- ) Print the vocabulary search order
|
||||
SEALED ( -- ) Alter the last vocabulary defined so it doesn't chain
|
||||
</pre>
|
||||
|
||||
<h5>Blocks</h5>
|
||||
<pre>
|
||||
USE ( "name" -- ) Use "name" as the blockfile, e.g. USE /spiffs/foo
|
||||
OPEN-BLOCKS ( a n -- ) Open a file as the block file
|
||||
LOAD ( n -- ) Evaluate a block
|
||||
THRU ( a b -- ) Load blocks a thru b
|
||||
LIST ( n -- ) List a block
|
||||
BLOCK ( n -- a ) Get a 1024 byte block
|
||||
BUFFER ( n -- a ) Get a 1024 byte block without regard to old contents
|
||||
UPDATE ( -- ) Mark the last block modified
|
||||
FLUSH ( -- ) Save and empty all buffers
|
||||
EMPTY-BUFFERS ( -- ) Empty all buffers
|
||||
SAVE-BUFFERS ( -- ) Save all buffers
|
||||
SCR ( -- a ) Pointer to last listed block
|
||||
</pre>
|
||||
|
||||
<h5>Block Editor</h5>
|
||||
These words are available inside the <code>EDITOR</code> vocabulary.
|
||||
<pre>
|
||||
WIPE ( -- ) Blank out the current block
|
||||
L ( -- ) List the current block
|
||||
D ( n -- ) Delete a line in the current block
|
||||
E ( n -- ) Clear a line in the current block
|
||||
R ( n "text" -- ) Replace a line in the current block
|
||||
A ( n "text" -- ) Add (insert) a line in the current block
|
||||
P ( -- ) Move to the previous block
|
||||
N ( -- ) Move to the next block
|
||||
</pre>
|
||||
|
||||
<h5>Utilities</h5>
|
||||
<pre>
|
||||
SEE ( "name" -- ) Attempt to decompile a word
|
||||
ECHO ( -- a ) -- Address of flag that determines if commands are echoed
|
||||
</pre>
|
||||
|
||||
<h3>Windows</h3>
|
||||
|
||||
<h4>Windows Opcodes</h4>
|
||||
|
||||
<p>
|
||||
The wealth of Windows .DLL and system functionality can be
|
||||
accessed via the dynamic loading interface.
|
||||
A handle to a library is obtained with <code>LOADLIBRARYA</code>,
|
||||
and then individual symbols are accessed with <code>GETPROCADDRESS</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
LOADLIBRARYA ( dllname-z -- module )
|
||||
GETPROCADDRESS ( module name-z -- fn )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
And assembly version of <code>*/MOD</code> is provided to allow the EXE to build without
|
||||
including MSVCRT.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/windows/windows_main.c">windows_main.c</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Native functions all called with CALL(n) (see Windows & Linux Calling below).
|
||||
</p>
|
||||
|
||||
<h4>Windows Imports</h4>
|
||||
|
||||
<p>
|
||||
Various Win32 calls are imported in
|
||||
<a href="https://github.com/flagxor/eforth/blob/main/ueforth/windows/windows.fs">windows.fs</a>.
|
||||
In addition, a terminal that responds to ANSI escape codes is created and connected to
|
||||
<code>TYPE</code> and <code>KEY</code>.
|
||||
</p>
|
||||
|
||||
<h3>Windows & Linux Calling</h3>
|
||||
|
||||
<p>
|
||||
As unfortunately both Windows and Linux have system and library calls with
|
||||
as many as 10 parameters (for example <code>XCreateImage</code>),
|
||||
a collection of calling thunks is required.
|
||||
A single varidic thunk would be ideal, but is hard to do without per platform
|
||||
assembly language.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
CALL0 ( fn -- n )
|
||||
CALL1 ( n fn -- n )
|
||||
CALL2 ( n n fn -- n )
|
||||
CALL3 ( n n n fn -- n )
|
||||
CALL4 ( n n n n fn -- n )
|
||||
CALL5 ( n n n n n fn -- n )
|
||||
CALL6 ( n n n n n n fn -- n )
|
||||
CALL7 ( n n n n n n n fn -- n )
|
||||
CALL7 ( n n n n n n n n fn -- n )
|
||||
CALL9 ( n n n n n n n n n fn -- n )
|
||||
CALL10 ( n n n n n n n n n n fn -- n )
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/eforth/blob/main/ueforth/common/calling.h">calling.h</a>.
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user