philburk / pforth Goto Github PK
View Code? Open in Web Editor NEWPortable Forth in C
License: BSD Zero Clause License
Portable Forth in C
License: BSD Zero Clause License
Dear Mr. Phil Burk,
I'm a user of pForth and very happy to use it. By the way, I have a question
about the following parts,
$ pforth -q
7.7e fround . 8
7.7e fround f. 0.0000000 Stack<10> 8
THROW code = -45
Float Stack underflow!
bye
$
Is this the correct behavior? I expected the following behavior,
$ pforth -q
7.7e fround f. 8.000000
bye
$
I would like to think the fround word should push its result to floating point
stack. If this question was a known issue, I did very rudely, so I'm very sorry.
Finally, I modified csrc/pfinnrfp.h to get my expected behavior,
$ diff -C 2 pfinnrfp.h.orig pfinnrfp.h
*** pfinnrfp.h.orig Mon Oct 28 15:50:40 2019
--- pfinnrfp.h Mon Oct 28 15:30:43 2019
***************
*** 207,213 ****
case ID_FP_FROUND:
! PUSH_TOS;
! TOS = (cell_t)fp_round(FP_TOS);
! M_FP_DROP;
break;
--- 207,211 ----
case ID_FP_FROUND:
! FP_TOS = (PF_FLOAT) fp_round(FP_TOS);
break;
$
Sincerely,
Hajime Edakawa
this would make it much easier to make software that is portable across multiple forth implementations.
I think that S" should use two storage areas to avoid collisions.
INCORRECT RESULT: T{ S" abcd" S" 1234" SSQ13 S= ROT ROT SSQ12 S= -> TRUE TRUE }T
WOW. Not sure how you are supposed to run the benchmarks in bench.fth, but I just added a line at the end to call one of the benchmarks and use the unix time command to run the benchmark like this:
time ./build/unix/pforth_standalone fth/bench.fth
So I edited bench.fth and added to the end of the file:
cr ." bench1" cr
BENCH1
Then edited and changed to bench2, etc.
All this is on my M1 Max MacBook Pro. All sub .1 seconds. Amazing how slow the machines you used to use to benchmark pForth! :)
bench1:
time ./build/unix/pforth_standalone fth/bench.fth
PForth V28-LE/64, built Dec 11 2022 11:52:21 (static)
Including: fth/bench.fth
bench1
./build/unix/pforth_standalone fth/bench.fth 0.03s user 0.00s system 98% cpu 0.036 total
bench2:
time ./build/unix/pforth_standalone fth/bench.fth
PForth V28-LE/64, built Dec 11 2022 11:52:21 (static)
Including: fth/bench.fth
bench2
./build/unix/pforth_standalone fth/bench.fth 0.05s user 0.00s system 98% cpu 0.050 total
bench3:
time ./build/unix/pforth_standalone fth/bench.fth
PForth V28-LE/64, built Dec 11 2022 11:52:21 (static)
Including: fth/bench.fth
bench3
./build/unix/pforth_standalone fth/bench.fth 0.05s user 0.00s system 93% cpu 0.050 total
bench4:
time ./build/unix/pforth_standalone fth/bench.fth
PForth V28-LE/64, built Dec 11 2022 11:52:21 (static)
Including: fth/bench.fth
bench4
./build/unix/pforth_standalone fth/bench.fth 0.04s user 0.00s system 97% cpu 0.039 total
bench5:
time ./build/unix/pforth_standalone fth/bench.fth
PForth V28-LE/64, built Dec 11 2022 11:52:21 (static)
Including: fth/bench.fth
bench5
./build/unix/pforth_standalone fth/bench.fth 0.05s user 0.00s system 98% cpu 0.054 total
sieve:
time ./build/unix/pforth_standalone fth/bench.fth
PForth V28-LE/64, built Dec 11 2022 11:52:21 (static)
Including: fth/bench.fth
sieve cr10 iterations
1899 primes
./build/unix/pforth_standalone fth/bench.fth 0.01s user 0.00s system 94% cpu 0.016 total
BYE on old Debian version printed stack trace and "AUTO.TERM".
Current code just exits without even a newline.
See #80
I exported the protect to Code::Blocks and i tried to compile it. It stops before building the executable 'cuz it doesn't find some '-l*.lib' libraries. Can you please pass me a makefile for the mingw32-make.exe and mingw32-gcc.exe that Code::Blocks has?
Hey @philburk ,
pforth builds on macos but not linux, using the build/unix directory. it used to work on linux, but no more.
It seems VPATH is not being honored by gnu make 4.3 for the .c files. This is a fresh clone of the repo:
(build/unix)> make all
make: *** No rule to make target 'pf_cglue.o', needed by 'pforth'. Stop.
Output of make -d
To REPRODUCE type in a line of code.
Then up up arrow to try to get that line back for editing.
Expect to see line editing like in Unix shell.
Actually see garbage escape characters in terminal.
pForth has a problem with this test from the forth2012-test-suite:
PForth V27-LE/64, built Dec 17 2016 18:35:01
pForth loading dictionary from file /scratch/forth/pforth/build/unix/pforth.dic
File format version is 9
Name space size = 120000
Code space size = 300000
Entry Point = 0
Cell Size = 8
Little Endian Dictionary
123 VALUE VAL3 IMMEDIATE ok
Stack<10>
: VD3 VAL3 LITERAL ; Stack<10> UNDERFLOW!
THROW code = -257
Stack depth changed between : and ; . Probably unbalanced conditional!
It uses DO instead of ?DO.
In the old Forths, 0 0 DO LOOP
would not execute. In ANSI Forth it will loop forever!
So it should use ?DO instead to handle the index 0 case.
Don't you want to add standard SEARCH-WORDLIST
word?
Cannot compile pForth with multiple cores (make -jX for example -j2 -j4 -j8) on Linux (ie Debian 9.3) Got the (translated) failure:
cd pforth/build/unix
make -j2
../../csrc/pf_save.c:42:26: fatal error: pfdicdat.h: no such file or directory
compilation terminated.
Makefile:80 : target « pf_save.eo » failed
while make
alone works and finish compiling. I think its just a story of order prerequisites and just a |
is missing (but I failed to place it correctly). See http://www.gnu.org/software/make/manual/make.html#Prerequisite-Types
pForth Reference Manual says it supports ?
, however:
PForth V27-LE/32, built Sep 13 2017 21:10:14
pForth loading dictionary from file pforth.dic
File format version is 9
Name space size = 120000
Code space size = 300000
Entry Point = 0
Cell Size = 4
Little Endian Dictionary
4 constant four ok
Stack<10> ' four ? ? ? - unrecognized word!
Stack<10> 43508
THROW code = -13
Undefined word!
These all look similar to this:
/usr/include/features.h:183:3: warning: #warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" [-Wcpp]
# warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"
As an option.
Use tests from here:
https://thebeez.home.xs4all.nl/4tH/
For continuous integration.
Travis may be going away and GitHub Actions is easier.
Words that were meant to be hidden are not, for example: KH.COMPARE
Also PRIVATE-START and PRIVATE-STOP are not zero. Maybe check for that and warn in PRIVATE{
The code
: TEST-T 1 THROW ;
: TEST 3 ['] TEST-T CATCH ;
TEST . . DEPTH . CR
prints 1 3 0
on latest Gforth and VFX, but 1 1 0
on latest pForth git. I can’t point to a particular sentence in the standard, but I’d expect that if the code inside the CATCH
didn’t touch an item on the stack, that item would be unaffected by the THROW
.
We fail if the C build fails but not if we break the Forth.
May need to throw an exception or pass back a return code so pForth main returns 1.
Then we can detect that and return 1 from the Travis execution.
I was build a pforth_standalone and not getting the new changes.
It turned out that I was accidentally picking up an old "csrc/pfdicdat.h" file.
I tried to modify the Makefile so it would abort if detected but couldn't get that to work.
So I just print a warning and delete "csrc/pfdicdat.h".
I can't access the documentation at https://www.softsynth.com/pforth/. In fact, I can't even ping that domain. Since I can't find the docs here on GitHub, is it hosted anywhere else?
I'm able to compile and run pForth for Windows/AMD64 using Visual Studio 2019. I'm seeing several compiler warnings though:
philburk-pforth-dd36def\csrc\pf_inner.c(204,69): warning C4293: '>>': shift count negative or too big, undefined behavior
philburk-pforth-dd36def\csrc\pf_save.c(410,75): warning C4244: '=': conversion from 'cell_t' to 'uint32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(412,102): warning C4267: '=': conversion from 'size_t' to 'int32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(413,106): warning C4267: '=': conversion from 'size_t' to 'int32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(414,41): warning C4244: '=': conversion from 'cell_t' to 'int32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(438,38): warning C4244: '=': conversion from 'ExecToken' to 'int32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(456,55): warning C4244: '=': conversion from 'cell_t' to 'int32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(457,78): warning C4244: '=': conversion from 'cell_t' to 'uint32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(469,34): warning C4244: '=': conversion from 'cell_t' to 'int32_t', possible loss of data
philburk-pforth-dd36def\csrc\pf_save.c(476,30): warning C4244: '=': conversion from 'cell_t' to 'int32_t', possible loss of data
Regarding the possible loss of data warnings: these seem, at a glance, to be well-founded. For instance, peering through the typedefs, the conversion from 'ExecToken' to 'int32_t'
boils down to a uintptr_t
being converted to an int32_t
.
There are also some compiler warnings on 32-bit builds, but these ones seem spurious, as all 4 of the lines are wrapped within if( sizeof(ucell_t) == 8 ) {
and so will not be executed on 32-bit builds.
philburk-pforth-dd36def\csrc\pf_save.c(223,38): warning C4293: '>>': shift count negative or too big, undefined behavior
philburk-pforth-dd36def\csrc\pf_save.c(224,38): warning C4293: '>>': shift count negative or too big, undefined behavior
philburk-pforth-dd36def\csrc\pf_save.c(225,38): warning C4293: '>>': shift count negative or too big, undefined behavior
philburk-pforth-dd36def\csrc\pf_save.c(226,38): warning C4293: '>>': shift count negative or too big, undefined behavior
It's possible to get rid of these warnings using the preprocessor, following this documentation, something like this (non-Windows builds will be unaffected):
/* 32-bit Windows builds definitely don't need the first
sequence. This avoid spurious Visual Studio warnings. */
#if (!defined _WIN32) || (defined _WIN64)
if( sizeof(ucell_t) == 8 )
{
*addr++ = (uint8_t) (data>>56);
*addr++ = (uint8_t) (data>>48);
*addr++ = (uint8_t) (data>>40);
*addr++ = (uint8_t) (data>>32);
}
#endif
*addr++ = (uint8_t) (data>>24);
*addr++ = (uint8_t) (data>>16);
*addr++ = (uint8_t) (data>>8);
*addr = (uint8_t) (data);
I'm running Windows 10/AMD64. I compiled pForth using Visual Studio 2019.
I'm able to run pForth from PowerShell or from the old cmd
terminal and interactive usage works fine, but if I try to run it from the MiniGW Bash terminal (the one that ships with Git for Windows), pForth doesn't behave as expected. It seems not to ever receive commands typed into the prompt. Pressing enter does not have the effect of submitting a line to pForth for processing.
For comparison, Gforth runs fine in all three terminals.
Perhaps related to the use of getchar?
Hello!
I have made an (unofficial) package of PForth for OpenWRT, and while cross-compiling, I noticed that the dictionary buillt on the compiling machine (amd64) had a cell size not compatible with the device I was compiling to (32 bit big-endian MIPS).
So I made the package installer do this:
/tmp/pforth-install/fth
(/tmp
is mounted on RAM - I did this because even those ~300k may be too much for some devices)/tmp/pforth-install/fth
However, it would be easier if one could cross-build the dictionary. Would it be too hard to implement?
Using current pforth from github and the system.fth file from Debian's pforth package (which is at V21), I get a segfault. I put the system.fth file here: http://www.cyrius.com/tmp/system.fth
Starting program: /home/tbm/pforth-21/a/pforth/build/unix/pforth -i ../../../../system.fth
PForth V27-LE/64, built Jul 9 2015 16:56:37
Including: ../../../../system.fth
CELL redefined.
CELLS redefined.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000402090 in pfCatch (XT=2536) at ../../csrc/pf_inner.c:335
335 Token = READ_CELL_DIC(InsPtr++);
(gdb) where
#0 0x0000000000402090 in pfCatch (XT=2536) at ../../csrc/pf_inner.c:335
#1 0x00000000004095d5 in FindAndCompile (theWord=0x60eac0 "\a0BRANCHIG L PRIMITIVESILING ", '-' <repeats 40 times>, "*")
at ../../csrc/pfcompil.c:765
#2 0x00000000004097f6 in ffInterpret () at ../../csrc/pfcompil.c:849
#3 0x000000000040994f in ffOuterInterpreterLoop () at ../../csrc/pfcompil.c:919
#4 0x00000000004099a1 in ffIncludeFile (InputFile=0x62f790) at ../../csrc/pfcompil.c:942
#5 0x0000000000401bcd in pfIncludeFile (FileName=0x7fffffffecad "../../../../system.fth") at ../../csrc/pf_core.c:373
#6 0x0000000000401e8d in pfDoForth (DicFileName=0x0, SourceName=0x7fffffffecad "../../../../system.fth", IfInit=1) at ../../csrc/pf_core.c:550
#7 0x000000000040579e in main (argc=3, argv=0x7fffffffea28) at ../../csrc/pf_main.c:140
(gdb)
' XYZ ' could not find XYZStack<10>
It needs a CR at the end. Versus
XYZ XYZ ? - unrecognized word!
Stack<10>
I believe the linked stack comment is not correct:
Line 1137 in 34cc634
The ID_FILE_BIN primitive modifiers the TOS, so it should be:
( fam -- fam )
Hi,
I have a surprising phenomenon best explained by two code samples.
This one works as expected:
: foo-throw -888 .s throw ;
: foo-catch ['] foo-throw catch .s ;
0sp foo-catch
and yields:
Stack<10> -888
Stack<10> -888
When I complicate the invocation by passing another xt to the called word (in the real code I'm doing this for a reason), I will receive the throw code twice on the catch side, like so:
: bar-doit ( -- ) ." doing it!" cr ;
: bar-throw ( xt -- ) execute -999 .s throw ;
: bar-catch ( -- ) ['] bar-doit ['] bar-throw catch .s ;
0sp bar-catch
which yields:
doing it!
Stack<10> -999
Stack<10> -999 -999
There is a fix around exception handling in Helmut Eller's fork but that doesn't help for the case mentioned here.
Thanks for taking a look, Frank
The ID_PLUSLOOP_P
case in pf_inner.c uses 0x80000000
; presumably to extract the sign bit. This doesn't seem right for 64-bit machines.
in history.fth
ASCII_BACKSPACE OF kh.backspace ENDOF
ASCII_DELETE OF kh.backspace ENDOF
Should be
ASCII_DELETE OF kh.delete ENDOF
And in the end:
: AUTO.TERM
history.off
auto.init
;
should have auto.term, not auto.init
I'm interested in building pForth for an ARM Cortex-M micro-controller. I've looked at the existing Makefiles in platforms
but I can't figure out from that how to create one for, say, an Electro-Smith Daisy, a Raspberry Pi Pico or a Teensy. The Daisy and Pico have full C/C++ SDKs that run on Linux (and MacOS and Windows). I think there's an SDK for Teensy as well but I've only used the Arduino IDE with it.
How would I go about doing such a port? I am probably only going to need the CORE and BLOCK word sets in the final build, but I will eventually want to write a Forth-style assembler.
this can be verified by running echo "1000 msec bye" | time pforth
pforth version:
PForth V28-LE/64, built May 26 2022 12:08:16 (static)
commit: fa8de1f
also, why is MSEC
not named MS
, as the standard would say?
First error is
c99 -DPF_EMBEDDED=1 -I. -DPF_SUPPORT_FP -D_GNU_SOURCE -c -o pf_cglue.o ../../csrc/pf_cglue.c
In file included from ../../csrc/pf_all.h:50:0,
from ../../csrc/pf_cglue.c:19:
../../csrc/pf_io.h:87:42: error: unknown type name ‘off_t’
but I guess there'll be some more.
I have compiled and run pforth on a Microblaze soft-core on a Xilinx 7 FPGA. I followed the embedded instructions I think and set the appropriate flags, with the exception of the IO one as I just hacked my IO functions in a .c file versus making a separate one.
I SDAD the dictionary from an x86 and added it. Inspecting memory in the debugger, it appears to be assigned to the dic_HeaderBase
etc...
However in FindSpecialXTs
the code never returns from trying to find (QUIT)
. In ffFindNFA
, Searching
remains TRUE
and thus, never exits. I tried debugging further but I'm not familiar with the code so I think I'm at my limit here.
The first iteration of the do loop, the NameField
variable is \004;;;;
, the second time, it's p
the third it appears to be garbage. After that it is stuck in this loop.
The output of the terminal is below.
DBG: PForth V28-LE/32, built Sep 9 2019 17:22:25 (static)
static dic name size = 48940
DBG: static dic code size = 124956
DBG: pfAllocRawMem()
DBG: pfAllocRawMem()
DBG: pfAllocRawMem()
The code in pf_main.c that processes argc/argv doesn't make total sense to me.
You have a loop that processes argc arguments. If preceded with a -, you handle the flag(s). But if it's something like a string, you set SourceName to the argument.
Thus if you do something like:
./pforth foo bar
It tried to load bar and foo is ignored.
Maybe we can be a little more clever? How about, "load foo, execute word bar?"
But you also have to deal with:
./pforth foo bar baz
Should it execute words bar and baz?
Or maybe we do something even better.
./pforth foo -ebar baz
This loads foo.fth and runs word bar and passes baz as a command line argument to the forth code to be processed (like we do argc/argv in C).
Even better is:
./pforth foo -ebar -ebaz arg1 arg2
This loads foo, executes bar then baz, and passes arg1 and arg2 as argc/argv to the forth program
Also, maybe better to use getopt() ? (man 3 getopt) - exists on linux and macOS. This getopt() helper is really slick. It allows you to do '-efoo' and '-e foo' and does the right thing. Using it would also allow us to have something like ./pforth -h
that prints out help on the command line options.
Windows is the internet exploder of operating systems ;)
Also move original tests out of main fth folder.
Download suite from:
https://github.com/gerryjackson/forth2012-test-suite
Recommended by Stephen Pelc:
https://forth-standard.org/proposals/let-us-adopt-the-gerry-jackson-test-suite-as-part-of-forth-200x#contribution-63
Keep the V28 style for compatibility.
But call V29 the "2.0.0" version to be more modern.
Nowadays, the "build" folder is normally used for the output of the build.
It looks like the repo does not have OSS license.
relates to #73
relates to Homebrew/homebrew-core#57250
I suggest the readme.txt file be more explicit about how to build the dictionary file (pforth -i system.fth
), as it's currently not very 'discoverable' for newcomers. Personally I googled it and found my way to this site, which spells out the steps.
I have made an (unofficial) package of PForth for OpenWRT (see #86 ). PForth runs fine, but without echoing input when the user types (the line is echoed at once when I type return).
This is strange because I remember having seeing in the source that PForth flushes the output after each char (or am I wrong?)
cd platforms/unix
make all
EXPECT build to work
ACTUAL
c99 -o pforth pf_cglue.o pf_clib.o pf_core.o pf_inner.o pf_io.o pf_io_none.o pf_main.o pf_mem.o pf_save.o pf_text.o pf_words.o pfcompil.o pfcustom.o pf_io_posix.o pf_fileio_stdio.o -lm
wd=$(pwd); (cd ../../fth; ${wd}/pforth -i system.fth)
/bin/sh: 1: /home/parallels/Desktop/Parallels: not found
Makefile:103: recipe for target 'pforth.dic' failed
make: *** [pforth.dic] Error 127
It looks the spaces in the folder name are a problem. Once again!
I removed the spaces from the Folder name and it worked.
I should modify the Makefile so it is immune to spaces.
Extend the Wiki here:
https://github.com/philburk/pforth/wiki/Style-Guide
PForth V27-LE/32, built Sep 13 2017 21:10:14
pForth loading dictionary from file pforth.dic
File format version is 9
Name space size = 120000
Code space size = 300000
Entry Point = 0
Cell Size = 4
Little Endian Dictionary
4 constant four ok
Stack<10>
' four 8 dump
Segmentation fault
Different words handle stack-underflows differently. There is inconsistency between words, and also inconsistency within certain words, in that some words throw on some but not all underflow conditions.
A few examples:
.
detects when the stack is empty and throws+
, -
, *
, /
) throw if the stack is empty, but fail to throw when there's 1 value on the stack. The result of running one of these words when 1 value is on the stack, is an empty stack.CELLS
does not throw when the stack is empty (results in an empty stack)DUP
and 2DUP
do not detect when the stack is empty, and push garbage values in that circumstanceSWAP
does not detect if the stack is empty. If run when there is 1 value on the stack, the result is that the stack holds 1 value (of garbage).2SWAP
does something similar to SWAP
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.