On Friday, June 25, 2021 at 2:58:38 AM UTC-4, Ruvim wrote:
> On 2021-06-24 20:01, Jim Peterson wrote:
> > On Thursday, June 24, 2021 at 11:15:59 AM UTC-4, Ruvim wrote:
> >> Ideally, the definitions should be written as usual:
> >>
> >> : nip ( x2 x1 -- x1 ) swap drop ;
> >> : rot ( x3 x2 x1 -- x2 x1 x3 ) >r swap r> swap ;
> >>
> >> [snip]
> >
> > I think this is misleading, to have something look like a colon definition
> > yet not operate as such.
> It isn't.
>
> The idea is following.
>
> When "included" is applied to a file name, the file is loaded as usual.
>
> When "included-undefined" (the name is for example) is applied to the
I still don't think this is a good idea. Having some code that looks
extraordinarily similar to one, very familiar thing but is actually a
different thing due to the manner in which the code is incorporated
("included-undefined") feels far more prone to misinterpretation than using a
"?:" operator, which might put the reader off for a moment until the
definition/intent of that operator is discovered, but ultimately would serve
as a constant reminder of what the writer intended.
I took a crack at "?:"... it maybe works? (don't put a bare semicolon
anywhere but the end, though):
: ?:
>in @
bl word find nip
if
\ skip definition:
drop
begin
parse-name
dup if
s" ;" compare 0= if exit then
else
2drop
refill 0= abort" end of input during ?: definition"
then
again
else
\ rewind and define:
>in ! :
then
;
> > It is unfortunate that one can't simply,
> > iteratively PARSE-NAME / REFILL until getting to a ";". The loop would
> > have to account for "/"- and "("-style comments and occurences of S", C",
> > S\", and .(, as well as any possible, user-defined words with similar
> > behavior.
> It shows need of lexical blocks in Forth.
> >
> > Alternatively, one could simply declare that an isolated semicolon is not
> > allowed anywhere except at the actual end of a ?: definition.
> Alternatively, one could introduce full fledged lexical blocks.
Adding lexical blocks feels like a route towards some language that is no
longer Forth. I don't think it would make it any easier to skip over a word
definition, either, since the skipper would still need to recognize when some
text is in a string or comment, versus not.
On Friday, June 25, 2021 at 4:59:39 AM UTC-4, Anton Ertl wrote:
> Why would you call such an implementation "highly optimized"?
>
> Anyway, let's see:
>
> Linux/FORTH (C) 2005 Peter Fälth Version 1.6-982-823 Compiled on 2017-12-03
> [shockingly optimized code]
>
> VFX 4.72:
> [more shockingly optimized code]
>
> SwiftForth i386-Linux 3.11.0 23-Feb-2021
> [still more shockingly optimized code]
>
> iforth:
> [lots more shockingly optimized code]
I'm shocked. Also, I get totally different results, that are more along the
lines of what I expect:
0[sparkle:~/personal/src/repos/j3]1137: gforth
Gforth 0.7.3, Copyright (C) 1995-2008 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
: nip { x1 x0 } x0 ; redefined nip ok
see nip
: nip
>l >l @local1 lp+2 ; ok
see >l
Code >l
0x00005615e4c4f147 <gforth_engine+775>: mov %r15,0x1d812(%rip) # 0x5615e4c6c960 <saved_ip>
0x00005615e4c4f14e <gforth_engine+782>: mov (%r14),%rax
0x00005615e4c4f151 <gforth_engine+785>: sub $0x8,%rbx
0x00005615e4c4f155 <gforth_engine+789>: add $0x8,%r14
0x00005615e4c4f159 <gforth_engine+793>: add $0x8,%r15
0x00005615e4c4f15d <gforth_engine+797>: mov %rax,(%rbx)
0x00005615e4c4f160 <gforth_engine+800>: mov -0x8(%r15),%rcx
0x00005615e4c4f164 <gforth_engine+804>: jmpq *%rcx
end-code
ok
see @local1
Code @local1
0x00005615e4c4f292 <gforth_engine+1106>: mov %r15,0x1d6c7(%rip) # 0x5615e4c6c960 <saved_ip>
0x00005615e4c4f299 <gforth_engine+1113>: mov 0x8(%rbx),%rax
0x00005615e4c4f29d <gforth_engine+1117>: sub $0x8,%r14
0x00005615e4c4f2a1 <gforth_engine+1121>: add $0x8,%r15
0x00005615e4c4f2a5 <gforth_engine+1125>: mov %rax,(%r14)
0x00005615e4c4f2a8 <gforth_engine+1128>: mov -0x8(%r15),%rcx
0x00005615e4c4f2ac <gforth_engine+1132>: jmpq *%rcx
end-code
ok
see lp+2
Code lp+2
0x00005615e4c4f17e <gforth_engine+830>: mov %r15,0x1d7db(%rip) # 0x5615e4c6c960 <saved_ip>
0x00005615e4c4f185 <gforth_engine+837>: add $0x10,%rbx
0x00005615e4c4f189 <gforth_engine+841>: add $0x8,%r15
0x00005615e4c4f18d <gforth_engine+845>: mov -0x8(%r15),%rcx
0x00005615e4c4f191 <gforth_engine+849>: jmpq *%rcx
end-code
ok
I have no idea how to begin to write a system that would be able to interpret
the given source into such tight machine language as you've shown. The appeal
of Forth, to me, was the simplicity with which I believed word definitions
simply placed down a list of tokens (XTs) corresponding to words within the
definition, for the most part (with some special ones for if/else, literals,
etc). Such simplicity allows people like me to implement a relatively
powerful system on prototype processors that don't have cross-compilation
support.
> For the leaking loop, the unbalanced if, and the early exit no
> declaration is necessary: You can see that there is something fishy
> going on by seeing that different paths result in different stack
> depths. A declaration is useful for cases where the stack mistake is
> on a code fragment that is always executed by the word.
> |As programmers learned C with Classes or C++, they lost the ability to
> |quickly find the ``silly errors'' that creep into C programs through
> |the lack of checking. Further, they failed to take the precautions
> |against such silly errors that good C programmers take as a matter of
> |course. After all, ``such errors don't happen in C with Classes.''
> |Thus, as the frequency of run-time errors caused by uncaught argument
> |type errors goes down, their seriousness and the time needed to find
> |them goes up.
I feel like you're trying to say that I should just be able to look at the
code I've written and notice there is a problem with the stack. I am not
at that level of expertise. Stack imbalances are the number one cause of
errors in the Forth stuff I write, and I'd rather get an alert from the
compiler. Maybe just some training wheels that tell me "oh, this word exited
without the proper differential to DEPTH" at runtime? Even my attempt at
defining "?:", above, was originally flawed because I had forgotten the nip
after find and had drop instead of 2drop before the refill. A simple stack
check would have alerted me. Maybe something like below (though EXIT and
THROW will cause trouble):
--Jim
[UNDEFINED] cell- [IF] : cell- -1 cells + ; [THEN]
\ Make a temporary stack for depth checks:
create _depth_stack 128 cells allot
_depth_stack value _ds_ptr
: >d _ds_ptr ! _ds_ptr cell+ to _ds_ptr ; \ no overflow checking!
: d> _ds_ptr cell- to _ds_ptr _ds_ptr @ ; \ no underflow checking!
\ Optionally trap calls to ; :
: orig; postpone ; ;
defer ; immediate
' orig; is ;
\ two code fragments to be postponed:
: delta_depth depth + >d ;
: check_depth d> depth <> abort" stack depth mis-match" ;
\ The ; trap:
: check;
postpone check_depth
orig;
['] orig; is ;
;
\ The main word:
: check(
-1 0 ( dir sum )
begin
parse-name
2dup s" --" compare 0= if
2drop
swap negate swap
false
else
s" )" compare if
over +
false \ continue loop
else
true \ exit loop
then
then
until
nip
postpone literal
postpone delta_depth
['] check; is ;
; immediate
\ A demonstration:
: myword check( a b -- c )
over - \ oops, should have been "swap -"
;
1 2 myword \ causes an abort with appropriate stack trace