]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
support long definitions; add tests as submodule
authorClyne Sullivan <clyne@bitgloo.com>
Wed, 25 Oct 2023 13:06:14 +0000 (09:06 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Wed, 25 Oct 2023 13:06:14 +0000 (09:06 -0400)
.gitmodules [new file with mode: 0644]
Makefile
README.md
forth/core.fth
libalee/corewords.cpp
libalee/dictionary.cpp
tests [new submodule]

diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..14dfdda
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "tests"]
+       path = tests
+       url = https://github.com/gerryjackson/forth2012-test-suite
index d6c6eff402ca8aa6bcd2f93bd3e6659bb7e67186..e54b3fba47657a2ec3d862682114e9d932cf4b14 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,7 @@ cppcheck:
              libalee alee*.cpp *dict.hpp
 
 test: standalone
-       echo "\nbye\n" | ./alee-standalone forth/core-ext.fth forth/test/tester.fr forth/test/core.fr
+       echo "bye" | ./alee-standalone forth/core-ext.fth tests/src/tester.fr tests/src/core.fr
 
 $(LIBFILE): $(OBJFILES)
        $(AR) crs $@ $(OBJFILES)
index eca6085740c9c4ec97422cbb484f34015ddc8bb0..247624fc4b6352fd1f6df695f62d956dc2f93ad2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,27 +1,26 @@
 # Alee Forth
 
-Alee Forth is a concise Forth implementation written in modern C++ that aims for portability, minimal program size, and execution efficiency.
+Alee Forth is a concise Forth implementation written in modern C++ that aims for portability, minimal memory footprint, and execution efficiency.
 
 ## Cross-platform compatibility
 
-Alee Forth relies on the C++20 standard. It *does not* rely on any operating system. As a result, portability extends down to microcontroller targets with < 1 kB of memory. See the `msp430` folder for an example of such a port.
+Alee Forth relies on the C++20 standard. It *does not* rely on any operating system. As a result, portability extends down to microcontroller targets with < 16kB flash and < 1 kB of RAM. See the `msp430` folder for an example of such a port.
 
-System-specific functionality is obtained through a `sys` Forth word. This word calls a user-supplied C++ function that implements whatever functionality is needed.
+System-specific functionality is achieved through a `sys` Forth word. This word calls a user-supplied C++ function that implements whatever functionality is needed.
 
 ## Forth compatibility
 
-Alee implements the entire "core" and majority of the "core extension" [word-sets](https://forth-standard.org/standard/core). Implementation is tracked in `compat.txt` with missing words listed below. Fundamental words are hard-coded into Alee while the rest of the implementation is found in `forth/core.fth` and `forth/core-ext.fth`. Running Alee without these implementation files will leave you with a very minimal word-set. These files may be compiled into the Alee binary by building the `standalone` target.
+Alee Forth uses the [Forth 2012 test suite](https://github.com/gerryjackson/forth2012-test-suite) to ensure standards compliance. The entire "core" [word-set](https://forth-standard.org/standard/core) is implemented as well as most of the "core extension" word-set. The compiled program contains a minimal set of fundamental words with libraries in the `forth` directory supplying these larger word-sets. The "core" word-set can be compiled into the program by building the `standalone` target.
+
+**Missing** core extension words:
 
-**Missing** core extensions:  
 ```
 .R HOLDS PAD PARSE PARSE-NAME REFILL RESTORE-INPUT S\" SAVE-INPUT SOURCE-ID U.R U> UNUSED WITHIN [COMPILE]
 ```
 
-Alee aims for compliance with common Forth standards like Forth 2012 and ANS Forth. Compliance is tested using a [Forth 2012 test suite](https://github.com/gerryjackson/forth2012-test-suite). Supported test files are in the `test` directory with tests for unimplemented words commented out.
-
 ## Building
 
-Alee requires `make` and a compiler that supports C++20. Simply running `make` will produce the `libalee.a` library and a REPL binary named `alee`. You will likely want to pass in the core implementation files by calling `./alee forth/core.fth forth/core-ext.fth`.
+Alee requires `make` and a compiler that supports C++20. Simply running `make` will produce the `libalee.a` library and a REPL binary named `alee`. The core word-sets can be passed into `alee` via the command line: `./alee forth/core.fth forth/core-ext.fth`.
 
 Other available build targets:
 
@@ -30,5 +29,5 @@ Other available build targets:
 * `standalone`: Builds the core dictionary (`core.fth`) into the binary.
 * `msp430-prep` and `msp430`: Builds a binary for the [MSP430G2553](https://www.ti.com/product/MSP430G2553) microcontroller. See the `msp430` folder for more information.
 
-If building for a new platform, review these files: `Makefile`, `libalee/types.hpp`, and `libalee/state.hpp`.
+If building for a new platform, review these files: `Makefile`, `libalee/types.hpp`, and `libalee/state.hpp`. It is possible to modify the implementation to use 32-bit words, but this will require re-writing the core word-sets.
 
index 071af33f1776f04914ffba0a595b5b90c7e5d6b9..360d269330e7f1de8bd6c578920667dd0e0537ab 100644 (file)
            swap postpone literal postpone literal ; imm
 : ."       postpone s" state @ if ['] type , else type then ; imm
 
-: create   align here
-           1 cells 1 chars - allot
-           bl word count swap drop
-           1 chars allot
-           swap over over ! swap allot align
+: create   align here dup _latest @ - 1 1 cells 8 * 6 - << 1- swap <=
+           dup if -1 6 << , then 0 , >r
+           begin key? if key else bl then dup bl <> while
+           c, 1 over +! repeat drop align
            ['] _lit , here 3 cells + , ['] exit dup , ,
-           dup @ 31 & over _latest @ - 6 << or over ! _latest ! ;
+           dup _latest @ - r> if
+           over cell+ else 6 << over then +! _latest ! ;
+
 : _does>   _latest @ dup @ 31 & + cell+ aligned 2 cells +
            ['] _jmp over ! cell+
            r@ 1 cells - @ swap ! ;
index 62b03223b6514875659b99dfa193a0b8f0023312..1a39b7e174912bdf4884427a1a3eebe15e090c90 100644 (file)
@@ -178,8 +178,14 @@ execute:
 
         cell = state.pop();
         dcell = (cell - state.dict.latest()) << 6;
-        state.dict.write(cell,
-            (state.dict.read(cell) & 0x1F) | static_cast<Cell>(dcell));
+        if (dcell > (((1 << (sizeof(Cell) * 8 - 6)) - 1) << 6)) {
+            state.dict.write(cell,
+                (state.dict.read(cell) & 0x1F) | static_cast<Cell>(((1 << (sizeof(Cell) * 8 - 6)) - 1) << 6));
+            state.dict.write(static_cast<Addr>(cell) + sizeof(Cell), static_cast<Cell>(dcell >> 6));
+        } else {
+            state.dict.write(cell,
+                (state.dict.read(cell) & 0x1F) | static_cast<Cell>(dcell));
+        }
         state.dict.latest(cell);
         break;
     case 27: // _jmp0
index 0d225e052d83681d9af3cb7fab7b77849df5153f..6c359bd0210747acaf095c6ceffb8ed15183d467 100644 (file)
@@ -64,6 +64,9 @@ void Dictionary::addDefinition(Word word) noexcept
     Cell wsize = word.size();
     add(wsize);
 
+    if (alignhere() - latest() >= ((1 << (sizeof(Cell) * 8 - 6)) - 1))
+        add(0);
+
     auto addr = allot(wsize);
     auto it = word.begin(this);
     const auto end = word.end(this);
@@ -81,14 +84,25 @@ Addr Dictionary::find(Word word) noexcept
     for (;;) {
         const Addr l = read(lt);
         const Addr len = l & 0x1F;
+        Word lw;
 
-        const auto lw = Word::fromLength(lt + sizeof(Cell), len);
-        if (equal(word, lw))
-            return lt;
-        else if (lt == Begin)
-            break;
-        else
-            lt -= l >> 6;
+        if ((l >> 6) < 1023) {
+            lw = Word::fromLength(lt + sizeof(Cell), len);
+            if (equal(word, lw))
+                return lt;
+            else if (lt == Begin)
+                break;
+            else
+                lt -= l >> 6;
+        } else {
+            lw = Word::fromLength(lt + 2 * sizeof(Cell), len);
+            if (equal(word, lw))
+                return lt;
+            else if (lt == Begin)
+                break;
+            else
+                lt -= static_cast<Addr>(read(lt + sizeof(Cell)));
+        }
     }
 
     return 0;
@@ -96,8 +110,13 @@ Addr Dictionary::find(Word word) noexcept
 
 Addr Dictionary::getexec(Addr addr) noexcept
 {
-    const Addr len = read(addr) & 0x1Fu;
+    const Addr l = read(addr);
+    const Addr len = l & 0x1Fu;
+
     addr += sizeof(Cell);
+    if ((l >> 6) == 1023)
+        addr += sizeof(Cell);
+
     addr += len;
     return aligned(addr);
 }
diff --git a/tests b/tests
new file mode 160000 (submodule)
index 0000000..45b7ecc
--- /dev/null
+++ b/tests
@@ -0,0 +1 @@
+Subproject commit 45b7ecc1e37d8fdd1bd9a29ec52a15bf7ac69d7f