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
;
25 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26 ;; working with
double (64-bit
) numbers
29 ;; convert single number
do double number
30 : S
>D
( n
-- nl nh
) DUP
0< IF -1 ELSE 0 ENDIF ;
31 : U
>D
( n
-- nl nh
) 0 ;
32 : D
>S
( lo hi
-- lo
) DROP
;
34 : DNEGATE
( lo hi
-- lo hi
) BITNOT SWAP BITNOT SWAP
1 0 D
+ ;
36 : D
<> ( lo0 hi0 lo1 hi1
-- bool
) D
= NOT
;
37 : D
>= ( lo0 hi0 lo1 hi1
-- bool
) D
< NOT
;
38 : D
> ( lo0 hi0 lo1 hi1
-- bool
) D
<= NOT
;
40 : DU
>= ( lo0 hi0 lo1 hi1
-- bool
) DU
< NOT
;
41 : DU
> ( lo0 hi0 lo1 hi1
-- bool
) DU
<= NOT
;
43 : D0
< ( lo hi
-- bool
) NIP
0< ;
44 : D0
> ( lo hi
-- bool
) NIP
0> ;
45 : D0
= ( lo hi
-- bool
) OR
0= ;
46 : D0
<> ( lo hi
-- bool
) OR
0<> ;
48 : D2*
( lo hi
-- lo hi
) 2DUP D
+ ;
49 : D2
/ ( lo hi
-- lo hi
) DUP
>R
-1 ASH SWAP
-1 LSH R
> 1 AND
IF 0x8000_
0000 OR
ENDIF SWAP
;
51 : DABS
( lo hi
-- lo hi
) DUP
0< IF DNEGATE
ENDIF ;
53 : DMAX
( d1 d2
-- max
[d1
,d2
] ) 2over
2over d
< if 2swap
endif 2drop
;
54 : DMIN
( d1 d2
-- min
[d1
,d2
] ) 2over
2over d
> if 2swap
endif 2drop
;
55 : 2ROT
( x1 x2 x3 x4 x5 x6
-- x3 x4 x5 x6 x1 x2
) 2>r
2swap
2r
> 2swap
;
56 : 2NROT
( x1 x2 x3 x4 x5 x6
-- x5 x6 x1 x2 x3 x4
) 2swap
2>r
2swap
2r
> ;
58 : M
+ ( d1|ud1 n
-- d2|ud2
) S
>D D
+ ;
61 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62 ;; some standard words
66 COMPILER
:(CREATE
-NAMELESS
)
67 COMPILER
:(CTLID
-COLON
)
68 ] ;; turn on the compiler
69 COMPILER
:(TRACE
-COLON
) ;; call tracer
72 : DEPTH
( -- data
-stack
-depth
)
73 MTASK
:ACTIVE
-STATE MTASK
:STATE
-SP@
76 ;; this is The Word that should be used
for vocabulary searches
77 ;; this does namespace resolution
78 ;; if "a:b" is not a known word
, try
to search
"b" in dictionary
"a"
79 ;; things like
"a:b:c" are allowed too
80 ;; returns `
1`
if cfa is immediate
, or `
-1`
if it is a normal word
81 : WFIND
( addr count
-- cfa
-1 // cfa
1 // false
)
83 DUP COMPILER
:IMMEDIATE
-WORD?
IF 1 ELSE -1 ENDIF
89 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
90 ;; additional string operations
92 ALSO STRING DEFINITIONS
94 : NCOUNT
( addr
-- addr
+4 bcount
)
95 DUP C@ SWAP CELL
+ SWAP
98 : CAT
-CHAR
( addr count char
-- addr count
+ )
103 : CAT
( addr count addr1 count1
-- addr count
+count1
)
113 ;; copy string
to PAD
(count is not set
)
114 : TO-PAD
( addr count
-- pad
+1 count
)
118 : CHAR
-UPPER
( ch
-- ch
)
119 0xff AND DUP
[CHAR
] a
[CHAR
] z BOUNDS?
IF 32 - ENDIF
122 : UPPER
( addr count
-- )
123 FOR DUP C@
[CHAR
] a
[CHAR
] z BOUNDS?
IF DUP C@
32 - OVER C
! ENDIF 1+ ENDFOR DROP
126 : -TRAILING
( addr count
-- addr count
)
131 DUP
1- C@A
+ BL
<= IF 1- FALSE
ELSE TRUE
ENDIF
136 ;; adjust the
character string at c
-addr1 by n characters
.
137 ;; the resulting
character string
, specified by c
-addr2 u2
,
138 ;; begins at c
-addr1 plus n characters and is u1 minus n characters long
.
139 ;; doesn
't check length, allows negative n.
140 : /STRING ( c-addr1 count n -- c-addr2 count )
141 DUP >R - SWAP R> + SWAP
144 ;; checks length, doesn't strip anything from an empty string
145 : /CHAR
( c
-addr1 u1
-- c
-addr
+1 u1
-1 )
146 DUP
0<= IF DROP
0 ELSE SWAP
1+ SWAP
1- ENDIF
149 ;; checks length
, doesn
't strip anything from an empty string
150 : /2CHARS ( c-addr1 u1 -- c-addr+2 u1-2 )
151 DUP 1 <= IF DROP 0 ELSE SWAP 2+ SWAP 2- ENDIF
154 : (CHAR-DIGIT) ( ch -- digit true // false )
156 [CHAR] 0 [CHAR] 9 BOUNDS-OF [CHAR] 0 - TRUE ENDOF
157 [CHAR] A [CHAR] Z BOUNDS-OF [CHAR] A - 10 + TRUE ENDOF
158 [CHAR] a [CHAR] z BOUNDS-OF [CHAR] a - 10 + TRUE ENDOF
159 OTHERWISE 2DROP FALSE
163 : DIGIT ( char base -- digit TRUE / FALSE )
164 SWAP (CHAR-DIGIT) IF ( base digit )
165 OVER 1 36 BOUNDS? IF ( base digit )
166 DUP ROT U< IF TRUE ELSE DROP FALSE ENDIF
167 ELSE ( base digit ) 2DROP FALSE
169 ELSE ( base ) DROP FALSE
173 : DIGIT? ( ch base -- flag ) DIGIT DUP IF NIP ENDIF ;
178 ;; +- ( n1 n2 -- n3 )
179 ;; Apply the sign of n2 to n1, which is left as n3.
181 SWAP 0< IF ABS NEGATE ELSE ABS ENDIF
185 : MEMCMP ( addr1 addr2 size -- n )
186 A>R >R 0 NROT R> ( 0 a1 a2 sz | rega )
187 FOR ( 0 a1 a2 | rega )
188 OVER >A C@A OVER >A C@A -
189 ?DUP IF ( 0 a1 a2 sgn ) >R DROP R> NROT BREAK ENDIF
196 : MEMCMP-CI ( addr1 addr2 size -- n )
197 A>R >R 0 NROT R> ( 0 a1 a2 sz | rega )
198 FOR ( 0 a1 a2 | rega )
199 OVER >A C@A STRING:CHAR-UPPER OVER >A C@A STRING:CHAR-UPPER -
200 ?DUP IF ( 0 a1 a2 sgn ) >R DROP R> NROT BREAK ENDIF
206 : UCMP ( a b -- -1|0|1 )
213 : COMPARE ( c-addr1 u1 c-addr2 u2 -- n )
214 rot 2dup 2>r umin memcmp ?dup ifnot 2r> swap ucmp else 2rdrop endif
217 : COMPARE-CI ( c-addr1 u1 c-addr2 u2 -- n )
218 rot 2dup 2>r umin memcmp-ci ?dup ifnot 2r> swap ucmp else 2rdrop endif
221 : FILL ( addr count byte -- )
223 SWAP FOR DUP I C!A+ ENDFOR DROP
227 : BLANKS ( addr count -- ) BL FILL ;
228 : ERASE ( addr count -- ) 0 FILL ;
230 : CMOVE ( source dest count -- )
231 \ ." CMOVE: from=" ROT DUP U. NROT
236 \ OVER C@ OVER C! 1+ SWAP 1+ SWAP
240 SWAP DUP >A 1+ SWAP ( source+1 dest ) -- source in A
241 C@A SWAP DUP >A 1+ SWAP ( source+1 dest+1 c ) -- dest in A
247 : CMOVE> ( source dest count -- )
248 \ ." CMOVE>: from=" ROT DUP U. NROT
253 >R SWAP R@ + SWAP R@ + R>
254 FOR ( source+count dest+count )
255 SWAP 1- DUP >A SWAP ( source-1 dest ) -- source-1 in A
256 C@A SWAP 1- DUP >A SWAP ( source-1 dest-1 c ) -- dest-1 in A
262 ;; uses CMOVE or CMOVE> (i.e. works like libc `memmove`)
263 ;; negative length does nothing (i.e. you cannot MOVE more that 2GB of data)
264 : MOVE ( from to len -- )
267 2DUP U< IF ;; from < to: may need to use CMOVE> (copy backwards)
269 ELSE ;; from > to: use CMOVE (normal forward copy)
277 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
278 ;; wordlist utilities
281 : (.-VOCID-NAME) ( vocid -- )
282 COMPILER:(VOCOFS-HEADER) + @
283 ?DUP IF STRING:NCOUNT XTYPE
288 : SHOW-WORDLISTS ( -- )
289 ." === WORDLISTS ===\n"
291 2 SPACES I 0 .R ." : " I (VSP-AT@) (.-VOCID-NAME) CR
293 ." CONTEXT: " CONTEXT @ (.-VOCID-NAME) CR
294 ." CURRENT: " CURRENT @ (.-VOCID-NAME) CR
300 : VOCID-WORDS ( vocid -- )
307 :iter LFA->NFA @ COMPILER:(WFLAG-SMUDGE) COMPILER:(WFLAG-HIDDEN) OR AND
309 :iter LFA->NFA STRING:NCOUNT ;; ( addr count )
310 :cols OVER + 1+ DUP TO :cols ;; ( addr count cols )
311 WORDS-WIDTH > IF DUP 1+ TO :cols CR ENDIF SPACE XTYPE
317 : WORDS ( -- ) CONTEXT @ VOCID-WORDS ;