1 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; and now
for something completely different
...
5 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 : USERVAR
( val
-- ) \ name
10 DUP CELL
+ (USER
-VAR
-ADDR
) (USER
-VAR
-SIZE
) + U
>= " too many user vars" ?ERROR
12 DUP CELL
+ (USER
-VAR
-USED
) !
16 : 2>R
( lo hi
-- | lo hi
) R
> ROT
>R SWAP
>R
>R
;
17 : 2R
> ( | lo hi
-- lo hi
) R
> R
> R
> SWAP ROT
>R
;
18 : 2R@
( | lo hi
-- lo hi | lo hi
) 2 RPICK
1 RPICK
;
19 : 2RDROP R
> RDROP RDROP
>R
;
22 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 ;; working with
double (64-bit
) numbers
26 ;; convert single number
do double number
27 : S
>D
( n
-- nl nh
) DUP
0< IF -1 ELSE 0 ENDIF ;
28 : U
>D
( n
-- nl nh
) 0 ;
29 : D
>S
( lo hi
-- lo
) DROP
;
31 : DNEGATE
( lo hi
-- lo hi
) BITNOT SWAP BITNOT SWAP
1 0 D
+ ;
33 : D
<> ( lo0 hi0 lo1 hi1
-- bool
) D
= NOT
;
34 : D
>= ( lo0 hi0 lo1 hi1
-- bool
) D
< NOT
;
35 : D
> ( lo0 hi0 lo1 hi1
-- bool
) D
<= NOT
;
37 : DU
>= ( lo0 hi0 lo1 hi1
-- bool
) DU
< NOT
;
38 : DU
> ( lo0 hi0 lo1 hi1
-- bool
) DU
<= NOT
;
40 : D0
< ( lo hi
-- bool
) NIP
0< ;
41 : D0
> ( lo hi
-- bool
) NIP
0> ;
42 : D0
= ( lo hi
-- bool
) OR
0= ;
43 : D0
<> ( lo hi
-- bool
) OR
0<> ;
45 : D2*
( lo hi
-- lo hi
) 2DUP D
+ ;
46 : D2
/ ( lo hi
-- lo hi
) DUP
>R
-1 ASH SWAP
-1 LSH R
> 1 AND
IF 0x8000_
0000 OR
ENDIF SWAP
;
48 : DABS
( lo hi
-- lo hi
) DUP
0< IF DNEGATE
ENDIF ;
50 : DMAX
( d1 d2
-- max
[d1
,d2
] ) 2over
2over d
< if 2swap
endif 2drop
;
51 : DMIN
( d1 d2
-- min
[d1
,d2
] ) 2over
2over d
> if 2swap
endif 2drop
;
52 : 2ROT
( x1 x2 x3 x4 x5 x6
-- x3 x4 x5 x6 x1 x2
) 2>r
2swap
2r
> 2swap
;
53 : 2NROT
( x1 x2 x3 x4 x5 x6
-- x5 x6 x1 x2 x3 x4
) 2swap
2>r
2swap
2r
> ;
55 : M
+ ( d1|ud1 n
-- d2|ud2
) S
>D D
+ ;
58 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
59 ;; some standard words
63 COMPILER
:(CREATE
-NAMELESS
)
64 COMPILER
:(CTLID
-COLON
)
65 ] ;; turn on the compiler
66 COMPILER
:(TRACE
-COLON
) ;; call tracer
69 : DEPTH
( -- data
-stack
-depth
)
70 MTASK
:ACTIVE
-STATE MTASK
:STATE
-SP@
73 ;; this is The Word that should be used
for vocabulary searches
74 ;; this does namespace resolution
75 ;; if "a:b" is not a known word
, try
to search
"b" in dictionary
"a"
76 ;; things like
"a:b:c" are allowed too
77 ;; returns `
1`
if cfa is immediate
, or `
-1`
if it is a normal word
78 : WFIND
( addr count
-- cfa
-1 // cfa
1 // false
)
80 DUP COMPILER
:IMMEDIATE
-WORD?
IF 1 ELSE -1 ENDIF
86 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
87 ;; additional string operations
89 ALSO STRING DEFINITIONS
91 : NCOUNT
( addr
-- addr
+4 bcount
)
92 DUP C@ SWAP CELL
+ SWAP
95 : CAT
-CHAR
( addr count char
-- addr count
+ )
100 : CAT
( addr count addr1 count1
-- addr count
+count1
)
110 ;; copy string
to PAD
(count is not set
)
111 : TO-PAD
( addr count
-- pad
+1 count
)
115 : CHAR
-UPPER
( ch
-- ch
)
116 0xff AND DUP
[CHAR
] a
[CHAR
] z BOUNDS?
IF 32 - ENDIF
119 : UPPER
( addr count
-- )
120 FOR DUP C@
[CHAR
] a
[CHAR
] z BOUNDS?
IF DUP C@
32 - OVER C
! ENDIF 1+ ENDFOR DROP
123 : -TRAILING
( addr count
-- addr count
)
128 DUP
1- C@A
+ BL
<= IF 1- FALSE
ELSE TRUE
ENDIF
133 ;; adjust the
character string at c
-addr1 by n characters
.
134 ;; the resulting
character string
, specified by c
-addr2 u2
,
135 ;; begins at c
-addr1 plus n characters and is u1 minus n characters long
.
136 ;; doesn
't check length, allows negative n.
137 : /STRING ( c-addr1 count n -- c-addr2 count )
138 DUP >R - SWAP R> + SWAP
141 ;; checks length, doesn't strip anything from an empty string
142 : /CHAR
( c
-addr1 u1
-- c
-addr
+1 u1
-1 )
143 DUP
0<= IF DROP
0 ELSE SWAP
1+ SWAP
1- ENDIF
146 ;; checks length
, doesn
't strip anything from an empty string
147 : /2CHARS ( c-addr1 u1 -- c-addr+2 u1-2 )
148 DUP 1 <= IF DROP 0 ELSE SWAP 2+ SWAP 2- ENDIF
151 : (CHAR-DIGIT) ( ch -- digit true // false )
153 [CHAR] 0 [CHAR] 9 BOUNDS-OF [CHAR] 0 - TRUE ENDOF
154 [CHAR] A [CHAR] Z BOUNDS-OF [CHAR] A - 10 + TRUE ENDOF
155 [CHAR] a [CHAR] z BOUNDS-OF [CHAR] a - 10 + TRUE ENDOF
156 OTHERWISE 2DROP FALSE
160 : DIGIT ( char base -- digit TRUE / FALSE )
161 SWAP (CHAR-DIGIT) IF ( base digit )
162 OVER 1 36 BOUNDS? IF ( base digit )
163 DUP ROT U< IF TRUE ELSE DROP FALSE ENDIF
164 ELSE ( base digit ) 2DROP FALSE
166 ELSE ( base ) DROP FALSE
170 : DIGIT? ( ch base -- flag ) DIGIT DUP IF NIP ENDIF ;
175 ;; +- ( n1 n2 -- n3 )
176 ;; Apply the sign of n2 to n1, which is left as n3.
178 SWAP 0< IF ABS NEGATE ELSE ABS ENDIF
182 : MEMCMP ( addr1 addr2 size -- n )
183 A>R >R 0 NROT R> ( 0 a1 a2 sz | rega )
184 FOR ( 0 a1 a2 | rega )
185 OVER >A C@A OVER >A C@A -
186 ?DUP IF ( 0 a1 a2 sgn ) >R DROP R> NROT BREAK ENDIF
193 : MEMCMP-CI ( addr1 addr2 size -- n )
194 A>R >R 0 NROT R> ( 0 a1 a2 sz | rega )
195 FOR ( 0 a1 a2 | rega )
196 OVER >A C@A STRING:CHAR-UPPER OVER >A C@A STRING:CHAR-UPPER -
197 ?DUP IF ( 0 a1 a2 sgn ) >R DROP R> NROT BREAK ENDIF
203 : UCMP ( a b -- -1|0|1 )
210 : COMPARE ( c-addr1 u1 c-addr2 u2 -- n )
211 rot 2dup 2>r umin memcmp ?dup ifnot 2r> swap ucmp else 2rdrop endif
214 : COMPARE-CI ( c-addr1 u1 c-addr2 u2 -- n )
215 rot 2dup 2>r umin memcmp-ci ?dup ifnot 2r> swap ucmp else 2rdrop endif
218 : FILL ( addr count byte -- )
220 SWAP FOR DUP I C!A+ ENDFOR DROP
224 : BLANKS ( addr count -- ) BL FILL ;
225 : ERASE ( addr count -- ) 0 FILL ;
227 : CMOVE ( source dest count -- )
228 \ ." CMOVE: from=" ROT DUP U. NROT
233 \ OVER C@ OVER C! 1+ SWAP 1+ SWAP
237 SWAP DUP >A 1+ SWAP ( source+1 dest ) -- source in A
238 C@A SWAP DUP >A 1+ SWAP ( source+1 dest+1 c ) -- dest in A
244 : CMOVE> ( source dest count -- )
245 \ ." CMOVE>: from=" ROT DUP U. NROT
250 >R SWAP R@ + SWAP R@ + R>
251 FOR ( source+count dest+count )
252 SWAP 1- DUP >A SWAP ( source-1 dest ) -- source-1 in A
253 C@A SWAP 1- DUP >A SWAP ( source-1 dest-1 c ) -- dest-1 in A
259 ;; uses CMOVE or CMOVE> (i.e. works like libc `memmove`)
260 ;; negative length does nothing (i.e. you cannot MOVE more that 2GB of data)
261 : MOVE ( from to len -- )
264 2DUP U< IF ;; from < to: may need to use CMOVE> (copy backwards)
266 ELSE ;; from > to: use CMOVE (normal forward copy)
274 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
275 ;; wordlist utilities
278 : (.-VOCID-NAME) ( vocid -- )
279 COMPILER:(VOCOFS-HEADER) + @
280 ?DUP IF STRING:NCOUNT XTYPE
285 : SHOW-WORDLISTS ( -- )
286 ." === WORDLISTS ===\n"
288 2 SPACES I 0 .R ." : " I (VSP-AT@) (.-VOCID-NAME) CR
290 ." CONTEXT: " CONTEXT @ (.-VOCID-NAME) CR
291 ." CURRENT: " CURRENT @ (.-VOCID-NAME) CR
297 : VOCID-WORDS ( vocid -- )
304 :iter LFA->NFA @ COMPILER:(WFLAG-SMUDGE) COMPILER:(WFLAG-HIDDEN) OR AND
306 :iter LFA->NFA STRING:NCOUNT ;; ( addr count )
307 :cols OVER + 1+ DUP TO :cols ;; ( addr count cols )
308 WORDS-WIDTH > IF DUP 1+ TO :cols CR ENDIF SPACE XTYPE
314 : WORDS ( -- ) CONTEXT @ VOCID-WORDS ;
317 : 2@ ( n -- lo hi ) DUP @ SWAP 4+ @ SWAP ;
318 : 2! ( lo hi n -- ) 2DUP ! NIP 4+ ! ;
319 : @EXECUTE ( addr ) @ EXECUTE-TAIL ;
320 : @EXECUTE-TAIL ( addr ) RDROP @ EXECUTE-TAIL ;
321 \ for MINIOOF and such
322 : (NOTIMPL) ( ) " not implemented" ERROR ;