hashtables bootstrap correctly
parent
0dfb0cf01e
commit
67af634d00
3
Makefile
3
Makefile
|
@ -24,7 +24,8 @@ OBJS = native/arithmetic.o native/array.o native/bignum.o \
|
||||||
native/unix/read.o \
|
native/unix/read.o \
|
||||||
native/unix/write.o \
|
native/unix/write.o \
|
||||||
native/unix/ffi.o \
|
native/unix/ffi.o \
|
||||||
native/debug.o
|
native/debug.o \
|
||||||
|
native/hashtable.o
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@echo "Run 'make' with one of the following parameters:"
|
@echo "Run 'make' with one of the following parameters:"
|
||||||
|
|
|
@ -29,6 +29,7 @@ IN: kernel-internals
|
||||||
USE: generic
|
USE: generic
|
||||||
USE: math-internals
|
USE: math-internals
|
||||||
USE: kernel
|
USE: kernel
|
||||||
|
USE: lists
|
||||||
|
|
||||||
! An array is a range of memory storing pointers to other
|
! An array is a range of memory storing pointers to other
|
||||||
! objects. Arrays are not used directly, and their access words
|
! objects. Arrays are not used directly, and their access words
|
||||||
|
@ -42,7 +43,7 @@ USE: kernel
|
||||||
|
|
||||||
BUILTIN: array 8
|
BUILTIN: array 8
|
||||||
|
|
||||||
: array-capacity ( array -- n ) 1 integer-slot ; inline
|
: array-capacity ( array -- n ) 1 slot ; inline
|
||||||
: vector-array ( vec -- array ) 2 slot ; inline
|
: vector-array ( vec -- array ) 2 slot ; inline
|
||||||
: set-vector-array ( array vec -- ) 2 set-slot ; inline
|
: set-vector-array ( array vec -- ) 2 set-slot ; inline
|
||||||
|
|
||||||
|
@ -51,3 +52,14 @@ BUILTIN: array 8
|
||||||
|
|
||||||
: set-array-nth ( obj n array -- )
|
: set-array-nth ( obj n array -- )
|
||||||
swap 2 fixnum+ set-slot ; inline
|
swap 2 fixnum+ set-slot ; inline
|
||||||
|
|
||||||
|
: (array>list) ( n i array -- list )
|
||||||
|
pick pick fixnum<= [
|
||||||
|
3drop [ ]
|
||||||
|
] [
|
||||||
|
2dup array-nth >r >r 1 fixnum+ r> (array>list) r>
|
||||||
|
swap cons
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: array>list ( n array -- list )
|
||||||
|
0 swap (array>list) ;
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
IN: image
|
IN: image
|
||||||
USE: errors
|
USE: errors
|
||||||
USE: generic
|
USE: generic
|
||||||
|
USE: kernel-internals
|
||||||
USE: hashtables
|
USE: hashtables
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: lists
|
USE: lists
|
||||||
|
@ -86,9 +87,9 @@ SYMBOL: boot-quot
|
||||||
: cons-tag BIN: 010 ; inline
|
: cons-tag BIN: 010 ; inline
|
||||||
: object-tag BIN: 011 ; inline
|
: object-tag BIN: 011 ; inline
|
||||||
|
|
||||||
: f-type 6 ; inline
|
|
||||||
: t-type 7 ; inline
|
: t-type 7 ; inline
|
||||||
: array-type 8 ; inline
|
: array-type 8 ; inline
|
||||||
|
: hashtable-type 10 ; inline
|
||||||
: vector-type 11 ; inline
|
: vector-type 11 ; inline
|
||||||
: string-type 12 ; inline
|
: string-type 12 ; inline
|
||||||
: word-type 17 ; inline
|
: word-type 17 ; inline
|
||||||
|
@ -142,6 +143,8 @@ GENERIC: ' ( obj -- ptr )
|
||||||
|
|
||||||
( Fixnums )
|
( Fixnums )
|
||||||
|
|
||||||
|
: emit-fixnum ( n -- ) fixnum-tag immediate emit ;
|
||||||
|
|
||||||
M: fixnum ' ( n -- tagged ) fixnum-tag immediate ;
|
M: fixnum ' ( n -- tagged ) fixnum-tag immediate ;
|
||||||
|
|
||||||
( Bignums )
|
( Bignums )
|
||||||
|
@ -154,7 +157,7 @@ M: bignum ' ( bignum -- tagged )
|
||||||
[[ 0 [ 1 0 ] ]]
|
[[ 0 [ 1 0 ] ]]
|
||||||
[[ -1 [ 2 1 1 ] ]]
|
[[ -1 [ 2 1 1 ] ]]
|
||||||
[[ 1 [ 2 0 1 ] ]]
|
[[ 1 [ 2 0 1 ] ]]
|
||||||
] assoc [ emit ] each align-here r> ;
|
] assoc unswons emit-fixnum [ emit ] each align-here r> ;
|
||||||
|
|
||||||
( Special objects )
|
( Special objects )
|
||||||
|
|
||||||
|
@ -175,7 +178,7 @@ M: f ' ( obj -- ptr )
|
||||||
: -1, -1 >bignum ' drop ;
|
: -1, -1 >bignum ' drop ;
|
||||||
|
|
||||||
( Beginning of the image )
|
( Beginning of the image )
|
||||||
! The image proper begins with the header, then T,
|
! The image begins with the header, then T,
|
||||||
! and the bignums 0, 1, and -1.
|
! and the bignums 0, 1, and -1.
|
||||||
|
|
||||||
: begin ( -- ) header t, 0, 1, -1, ;
|
: begin ( -- ) header t, 0, 1, -1, ;
|
||||||
|
@ -249,7 +252,7 @@ M: cons ' ( c -- tagged )
|
||||||
object-tag here-as swap
|
object-tag here-as swap
|
||||||
string-type >header emit
|
string-type >header emit
|
||||||
dup str-length emit
|
dup str-length emit
|
||||||
dup hashcode fixnum-tag immediate emit
|
dup hashcode emit-fixnum
|
||||||
pack-string
|
pack-string
|
||||||
align-here ;
|
align-here ;
|
||||||
|
|
||||||
|
@ -266,7 +269,7 @@ M: string ' ( string -- pointer )
|
||||||
[ ' ] map
|
[ ' ] map
|
||||||
object-tag here-as >r
|
object-tag here-as >r
|
||||||
array-type >header emit
|
array-type >header emit
|
||||||
dup length emit
|
dup length emit-fixnum
|
||||||
( elements -- ) [ emit ] each
|
( elements -- ) [ emit ] each
|
||||||
align-here r> ;
|
align-here r> ;
|
||||||
|
|
||||||
|
@ -274,7 +277,7 @@ M: string ' ( string -- pointer )
|
||||||
dup vector>list emit-array swap vector-length
|
dup vector>list emit-array swap vector-length
|
||||||
object-tag here-as >r
|
object-tag here-as >r
|
||||||
vector-type >header emit
|
vector-type >header emit
|
||||||
emit ( length )
|
emit-fixnum ( length )
|
||||||
emit ( array ptr )
|
emit ( array ptr )
|
||||||
align-here r> ;
|
align-here r> ;
|
||||||
|
|
||||||
|
@ -284,24 +287,30 @@ M: vector ' ( vector -- pointer )
|
||||||
: rehash ( hashtable -- )
|
: rehash ( hashtable -- )
|
||||||
! Now make a rehashing boot quotation
|
! Now make a rehashing boot quotation
|
||||||
dup hash>alist [
|
dup hash>alist [
|
||||||
>r dup vector-length [
|
over hash-clear
|
||||||
[ f swap pick set-vector-nth ] keep
|
|
||||||
] repeat r>
|
|
||||||
[ unswons rot set-hash ] each-with
|
[ unswons rot set-hash ] each-with
|
||||||
] cons cons
|
] cons cons
|
||||||
boot-quot [ append ] change ;
|
boot-quot [ append ] change ;
|
||||||
|
|
||||||
|
: emit-hashtable ( hash -- pointer )
|
||||||
|
dup buckets>list emit-array swap hash-size
|
||||||
|
object-tag here-as >r
|
||||||
|
hashtable-type >header emit
|
||||||
|
emit-fixnum ( length )
|
||||||
|
emit ( array ptr )
|
||||||
|
align-here r> ;
|
||||||
|
|
||||||
M: hashtable ' ( hashtable -- pointer )
|
M: hashtable ' ( hashtable -- pointer )
|
||||||
#! Only hashtables are pooled, not vectors!
|
#! Only hashtables are pooled, not vectors!
|
||||||
dup pooled-object [
|
dup pooled-object [
|
||||||
[ dup emit-vector [ pool-object ] keep ] keep rehash
|
[ dup emit-hashtable [ pool-object ] keep ] keep rehash
|
||||||
] ?unless ;
|
] ?unless ;
|
||||||
|
|
||||||
( End of the image )
|
( End of the image )
|
||||||
|
|
||||||
: vocabularies, ( vocabularies -- )
|
: vocabularies, ( vocabularies -- )
|
||||||
[
|
[
|
||||||
cdr dup vector? [
|
cdr dup hashtable? [
|
||||||
[
|
[
|
||||||
cdr dup word? [ word, ] [ drop ] ifte
|
cdr dup word? [ word, ] [ drop ] ifte
|
||||||
] hash-each
|
] hash-each
|
||||||
|
|
|
@ -218,11 +218,14 @@ vocabularies get [
|
||||||
[[ "vectors" ">vector" ]]
|
[[ "vectors" ">vector" ]]
|
||||||
[[ "strings" ">string" ]]
|
[[ "strings" ">string" ]]
|
||||||
[[ "words" ">word" ]]
|
[[ "words" ">word" ]]
|
||||||
|
[[ "hashtables" ">hashtable" ]]
|
||||||
[[ "kernel-internals" "slot" ]]
|
[[ "kernel-internals" "slot" ]]
|
||||||
[[ "kernel-internals" "set-slot" ]]
|
[[ "kernel-internals" "set-slot" ]]
|
||||||
[[ "kernel-internals" "integer-slot" ]]
|
[[ "kernel-internals" "integer-slot" ]]
|
||||||
[[ "kernel-internals" "set-integer-slot" ]]
|
[[ "kernel-internals" "set-integer-slot" ]]
|
||||||
[[ "kernel-internals" "grow-array" ]]
|
[[ "kernel-internals" "grow-array" ]]
|
||||||
|
[[ "hashtables" "<hashtable>" ]]
|
||||||
|
[[ "kernel-internals" "<array>" ]]
|
||||||
] [
|
] [
|
||||||
unswons create swap 1 + [ f define ] keep
|
unswons create swap 1 + [ f define ] keep
|
||||||
] each drop
|
] each drop
|
||||||
|
|
|
@ -39,7 +39,7 @@ USE: vectors
|
||||||
! Traits metaclass for user-defined classes based on hashtables
|
! Traits metaclass for user-defined classes based on hashtables
|
||||||
|
|
||||||
: traits ( object -- symbol )
|
: traits ( object -- symbol )
|
||||||
dup vector? [ \ traits swap hash ] [ drop f ] ifte ;
|
dup hashtable? [ \ traits swap hash ] [ drop f ] ifte ;
|
||||||
|
|
||||||
! Hashtable slot holding an optional delegate. Any undefined
|
! Hashtable slot holding an optional delegate. Any undefined
|
||||||
! methods are called on the delegate. The object can also
|
! methods are called on the delegate. The object can also
|
||||||
|
@ -58,7 +58,7 @@ SYMBOL: delegate
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: add-traits-dispatch ( word vtable -- )
|
: add-traits-dispatch ( word vtable -- )
|
||||||
>r unit [ car traits-dispatch call ] cons \ vector r>
|
>r unit [ car traits-dispatch call ] cons \ hashtable r>
|
||||||
set-vtable ;
|
set-vtable ;
|
||||||
|
|
||||||
\ traits [
|
\ traits [
|
||||||
|
|
|
@ -25,37 +25,45 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: kernel-internals
|
IN: hashtables
|
||||||
USE: generic
|
USE: generic
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: lists
|
USE: lists
|
||||||
USE: math
|
USE: math
|
||||||
USE: vectors
|
USE: vectors
|
||||||
|
|
||||||
: hash-array vector-array ; inline
|
BUILTIN: hashtable 10
|
||||||
: bucket-count >vector hash-array array-capacity ; inline
|
|
||||||
|
! A hashtable is implemented as an array of buckets. The
|
||||||
|
! array index is determined using a hash function, and the
|
||||||
|
! buckets are associative lists which are searched
|
||||||
|
! linearly.
|
||||||
|
|
||||||
|
IN: kernel-internals
|
||||||
|
|
||||||
|
: hash-array 2 slot ; inline
|
||||||
|
|
||||||
: hash-bucket ( n hash -- alist )
|
: hash-bucket ( n hash -- alist )
|
||||||
swap >fixnum swap >vector hash-array array-nth ; inline
|
swap >fixnum swap >hashtable hash-array array-nth ; inline
|
||||||
|
|
||||||
: set-hash-bucket ( obj n hash -- )
|
: set-hash-bucket ( obj n hash -- )
|
||||||
>r >fixnum r> hash-array set-array-nth ; inline
|
swap >fixnum swap >hashtable hash-array set-array-nth ;
|
||||||
|
inline
|
||||||
|
|
||||||
|
: hash-size+ ( hash -- )
|
||||||
|
>hashtable dup 1 slot 1 + swap 1 set-slot ; inline
|
||||||
|
|
||||||
|
: hash-size- ( hash -- )
|
||||||
|
>hashtable dup 1 slot 1 - swap 1 set-slot ; inline
|
||||||
|
|
||||||
IN: hashtables
|
IN: hashtables
|
||||||
|
|
||||||
! Note that the length of a hashtable vector must not change
|
: hash-size ( hash -- n )
|
||||||
! for the lifetime of the hashtable, otherwise problems will
|
#! Number of elements in the hashtable.
|
||||||
! occur. Do not use vector words with hashtables.
|
>hashtable 1 slot ;
|
||||||
|
|
||||||
PREDICATE: vector hashtable ( obj -- ? )
|
: bucket-count ( hash -- n )
|
||||||
[ assoc? ] vector-all? ;
|
>hashtable hash-array array-capacity ; inline
|
||||||
|
|
||||||
: <hashtable> ( buckets -- )
|
|
||||||
#! A hashtable is implemented as an array of buckets. The
|
|
||||||
#! array index is determined using a hash function, and the
|
|
||||||
#! buckets are associative lists which are searched
|
|
||||||
#! linearly. The number of buckets must be a power of two.
|
|
||||||
empty-vector ;
|
|
||||||
|
|
||||||
: (hashcode) ( key table -- index )
|
: (hashcode) ( key table -- index )
|
||||||
#! Compute the index of the bucket for a key.
|
#! Compute the index of the bucket for a key.
|
||||||
|
@ -74,6 +82,8 @@ PREDICATE: vector hashtable ( obj -- ? )
|
||||||
|
|
||||||
: set-hash* ( key table quot -- )
|
: set-hash* ( key table quot -- )
|
||||||
#! Apply the quotation to yield a new association list.
|
#! Apply the quotation to yield a new association list.
|
||||||
|
#! If the association list already contains the key,
|
||||||
|
#! decrement the hash size, since it will get removed.
|
||||||
>r
|
>r
|
||||||
2dup (hashcode)
|
2dup (hashcode)
|
||||||
r> pick >r
|
r> pick >r
|
||||||
|
@ -86,27 +96,46 @@ PREDICATE: vector hashtable ( obj -- ? )
|
||||||
#! Store the value in the hashtable. Either replaces an
|
#! Store the value in the hashtable. Either replaces an
|
||||||
#! existing value in the appropriate bucket, or adds a new
|
#! existing value in the appropriate bucket, or adds a new
|
||||||
#! key/value pair.
|
#! key/value pair.
|
||||||
|
dup hash-size+
|
||||||
[ set-assoc ] set-hash* ;
|
[ set-assoc ] set-hash* ;
|
||||||
|
|
||||||
: remove-hash ( key table -- )
|
: remove-hash ( key table -- )
|
||||||
#! Remove a value from a hashtable.
|
#! Remove a value from a hashtable.
|
||||||
[ remove-assoc ] set-hash* ;
|
[ remove-assoc ] set-hash* ;
|
||||||
|
|
||||||
: hash-each ( hash code -- )
|
: hash-clear ( hash -- )
|
||||||
#! Apply the code to each key/value pair of the hashtable.
|
#! Remove all entries from a hashtable.
|
||||||
swap [ swap dup >r each r> ] vector-each drop ; inline
|
dup bucket-count [
|
||||||
|
[ f swap pick set-hash-bucket ] keep
|
||||||
|
] repeat drop ;
|
||||||
|
|
||||||
|
: buckets>list ( hash -- list )
|
||||||
|
#! Push a list of key/value pairs in a hashtable.
|
||||||
|
dup bucket-count swap hash-array array>list ;
|
||||||
|
|
||||||
|
: (hash>alist) ( alist n hash -- alist )
|
||||||
|
2dup bucket-count >= [
|
||||||
|
2drop
|
||||||
|
] [
|
||||||
|
[ hash-bucket [ swons ] each ] 2keep
|
||||||
|
>r 1 + r> (hash>alist)
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: hash>alist ( hash -- alist )
|
||||||
|
#! Push a list of key/value pairs in a hashtable.
|
||||||
|
[ ] 0 rot (hash>alist) ;
|
||||||
|
|
||||||
|
: alist>hash ( alist -- hash )
|
||||||
|
dup length <hashtable> swap [ unswons pick set-hash ] each ;
|
||||||
|
|
||||||
: hash-keys ( hash -- list )
|
: hash-keys ( hash -- list )
|
||||||
#! Push a list of keys in a hashtable.
|
#! Push a list of keys in a hashtable.
|
||||||
[ ] swap [ car swons ] hash-each ;
|
hash>alist [ car ] map ;
|
||||||
|
|
||||||
: hash-values ( hash -- alist )
|
: hash-values ( hash -- alist )
|
||||||
#! Push a list of values in a hashtable.
|
#! Push a list of values in a hashtable.
|
||||||
[ ] swap [ cdr swons ] hash-each ;
|
hash>alist [ cdr ] map ;
|
||||||
|
|
||||||
: hash>alist ( hash -- list )
|
: hash-each ( hash code -- )
|
||||||
#! Push a list of key/value pairs in a hashtable.
|
#! Apply the code to each key/value pair of the hashtable.
|
||||||
[ ] swap [ swons ] hash-each ;
|
>r hash>alist r> each ; inline
|
||||||
|
|
||||||
: alist>hash ( alist -- hash )
|
|
||||||
37 <hashtable> swap [ unswons pick set-hash ] each ;
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ USE: math
|
||||||
|
|
||||||
: >n ( namespace -- n:namespace )
|
: >n ( namespace -- n:namespace )
|
||||||
#! Push a namespace on the namespace stack.
|
#! Push a namespace on the namespace stack.
|
||||||
>vector namestack cons set-namestack ; inline
|
>hashtable namestack cons set-namestack ; inline
|
||||||
|
|
||||||
: n> ( n:namespace -- namespace )
|
: n> ( n:namespace -- namespace )
|
||||||
#! Pop the top of the namespace stack.
|
#! Pop the top of the namespace stack.
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
IN: alien
|
IN: alien
|
||||||
|
USE: hashtables
|
||||||
DEFER: alien
|
DEFER: alien
|
||||||
DEFER: dll
|
DEFER: dll
|
||||||
|
|
||||||
|
@ -215,12 +216,15 @@ USE: words
|
||||||
[ >cons [ [ object ] [ cons ] ] ]
|
[ >cons [ [ object ] [ cons ] ] ]
|
||||||
[ >vector [ [ object ] [ vector ] ] ]
|
[ >vector [ [ object ] [ vector ] ] ]
|
||||||
[ >string [ [ object ] [ string ] ] ]
|
[ >string [ [ object ] [ string ] ] ]
|
||||||
[ >word [ [ word ] [ word ] ] ]
|
[ >word [ [ object ] [ word ] ] ]
|
||||||
|
[ >hashtable [ [ object ] [ hashtable ] ] ]
|
||||||
[ slot [ [ object fixnum ] [ object ] ] ]
|
[ slot [ [ object fixnum ] [ object ] ] ]
|
||||||
[ set-slot [ [ object object fixnum ] [ ] ] ]
|
[ set-slot [ [ object object fixnum ] [ ] ] ]
|
||||||
[ integer-slot [ [ object fixnum ] [ integer ] ] ]
|
[ integer-slot [ [ object fixnum ] [ integer ] ] ]
|
||||||
[ set-integer-slot [ [ integer object fixnum ] [ ] ] ]
|
[ set-integer-slot [ [ integer object fixnum ] [ ] ] ]
|
||||||
[ grow-array [ [ integer array ] [ object ] ] ]
|
[ grow-array [ [ integer array ] [ object ] ] ]
|
||||||
|
[ <hashtable> [ [ number ] [ hashtable ] ] ]
|
||||||
|
[ <array> [ [ number ] [ array ] ] ]
|
||||||
] [
|
] [
|
||||||
2unlist dup string? [
|
2unlist dup string? [
|
||||||
"stack-effect" set-word-property
|
"stack-effect" set-word-property
|
||||||
|
|
|
@ -58,3 +58,17 @@ f 100000000000000000000000000 "testhash" get set-hash
|
||||||
"visual basic" "testhash" get remove-hash
|
"visual basic" "testhash" get remove-hash
|
||||||
"visual basic" "testhash" get hash*
|
"visual basic" "testhash" get hash*
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
[ 4 ] [
|
||||||
|
"hey"
|
||||||
|
{{ [[ "hey" 4 ]] [[ "whey" 5 ]] }} 2dup (hashcode)
|
||||||
|
>r buckets>list r> [ cdr ] times car assoc
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
! Testing the hash element counting
|
||||||
|
|
||||||
|
<namespace> "counting" set
|
||||||
|
"key" "value" "counting" get set-hash
|
||||||
|
[ 1 ] [ "counting" get hash-size ] unit-test
|
||||||
|
"key" "value" "counting" get set-hash
|
||||||
|
[ 1 ] [ "counting" get hash-size ] unit-test
|
||||||
|
|
|
@ -78,7 +78,7 @@ unit-test
|
||||||
[ "funky" ] [ "funny-stack" get vector-pop ] unit-test
|
[ "funky" ] [ "funny-stack" get vector-pop ] unit-test
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
10 <vector> dup vector-array array-capacity
|
{ 1 2 3 4 } dup vector-array array-capacity
|
||||||
>r vector-clone vector-array array-capacity r>
|
>r vector-clone vector-array array-capacity r>
|
||||||
=
|
=
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
|
@ -36,11 +36,11 @@ USE: math-internals
|
||||||
|
|
||||||
BUILTIN: vector 11
|
BUILTIN: vector 11
|
||||||
|
|
||||||
: vector-length ( vec -- len ) >vector 1 integer-slot ; inline
|
: vector-length ( vec -- len ) >vector 1 slot ; inline
|
||||||
|
|
||||||
IN: kernel-internals
|
IN: kernel-internals
|
||||||
|
|
||||||
: (set-vector-length) ( len vec -- ) 1 set-integer-slot ; inline
|
: (set-vector-length) ( len vec -- ) 1 set-slot ; inline
|
||||||
|
|
||||||
: assert-positive ( fx -- )
|
: assert-positive ( fx -- )
|
||||||
0 fixnum<
|
0 fixnum<
|
||||||
|
@ -107,15 +107,8 @@ IN: vectors
|
||||||
: >pop> ( stack -- stack )
|
: >pop> ( stack -- stack )
|
||||||
dup vector-pop drop ;
|
dup vector-pop drop ;
|
||||||
|
|
||||||
: (vector>list) ( i vec -- list )
|
: vector>list ( vec -- list )
|
||||||
2dup vector-length >= [
|
dup vector-length swap vector-array array>list ;
|
||||||
2drop [ ]
|
|
||||||
] [
|
|
||||||
2dup vector-nth >r >r 1 + r> (vector>list) r> swons
|
|
||||||
] ifte ;
|
|
||||||
|
|
||||||
: vector>list ( str -- list )
|
|
||||||
0 swap (vector>list) ;
|
|
||||||
|
|
||||||
: vector-each ( vector quotation -- )
|
: vector-each ( vector quotation -- )
|
||||||
#! Execute the quotation with each element of the vector
|
#! Execute the quotation with each element of the vector
|
||||||
|
|
|
@ -5,7 +5,7 @@ F_ARRAY* allot_array(CELL type, CELL capacity)
|
||||||
{
|
{
|
||||||
F_ARRAY* array;
|
F_ARRAY* array;
|
||||||
array = allot_object(type,sizeof(F_ARRAY) + capacity * CELLS);
|
array = allot_object(type,sizeof(F_ARRAY) + capacity * CELLS);
|
||||||
array->capacity = capacity;
|
array->capacity = tag_fixnum(capacity);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,20 +22,30 @@ F_ARRAY* array(CELL capacity, CELL fill)
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void primitive_array(void)
|
||||||
|
{
|
||||||
|
F_FIXNUM capacity = to_fixnum(dpop());
|
||||||
|
if(capacity < 0)
|
||||||
|
general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
|
||||||
|
maybe_garbage_collection();
|
||||||
|
dpush(tag_object(array(capacity,F)));
|
||||||
|
}
|
||||||
|
|
||||||
F_ARRAY* grow_array(F_ARRAY* array, CELL capacity, CELL fill)
|
F_ARRAY* grow_array(F_ARRAY* array, CELL capacity, CELL fill)
|
||||||
{
|
{
|
||||||
/* later on, do an optimization: if end of array is here, just grow */
|
/* later on, do an optimization: if end of array is here, just grow */
|
||||||
int i;
|
int i;
|
||||||
F_ARRAY* new_array;
|
F_ARRAY* new_array;
|
||||||
|
CELL curr_cap = untag_fixnum_fast(array->capacity);
|
||||||
|
|
||||||
if(array->capacity >= capacity)
|
if(curr_cap >= capacity)
|
||||||
return array;
|
return array;
|
||||||
|
|
||||||
new_array = allot_array(untag_header(array->header),capacity);
|
new_array = allot_array(untag_header(array->header),capacity);
|
||||||
|
|
||||||
memcpy(new_array + 1,array + 1,array->capacity * CELLS);
|
memcpy(new_array + 1,array + 1,array->capacity * CELLS);
|
||||||
|
|
||||||
for(i = array->capacity; i < capacity; i++)
|
for(i = curr_cap; i < capacity; i++)
|
||||||
put(AREF(new_array,i),fill);
|
put(AREF(new_array,i),fill);
|
||||||
|
|
||||||
return new_array;
|
return new_array;
|
||||||
|
@ -43,8 +53,11 @@ F_ARRAY* grow_array(F_ARRAY* array, CELL capacity, CELL fill)
|
||||||
|
|
||||||
void primitive_grow_array(void)
|
void primitive_grow_array(void)
|
||||||
{
|
{
|
||||||
F_ARRAY* array = untag_array(dpop());
|
F_ARRAY* array;
|
||||||
CELL capacity = to_fixnum(dpop());
|
CELL capacity;
|
||||||
|
maybe_garbage_collection();
|
||||||
|
array = untag_array(dpop());
|
||||||
|
capacity = to_fixnum(dpop());
|
||||||
dpush(tag_object(grow_array(array,capacity,F)));
|
dpush(tag_object(grow_array(array,capacity,F)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,13 +71,15 @@ F_ARRAY* shrink_array(F_ARRAY* array, CELL capacity)
|
||||||
void fixup_array(F_ARRAY* array)
|
void fixup_array(F_ARRAY* array)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(i = 0; i < array->capacity; i++)
|
CELL capacity = untag_fixnum_fast(array->capacity);
|
||||||
|
for(i = 0; i < capacity; i++)
|
||||||
data_fixup((void*)AREF(array,i));
|
data_fixup((void*)AREF(array,i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_array(F_ARRAY* array)
|
void collect_array(F_ARRAY* array)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(i = 0; i < array->capacity; i++)
|
CELL capacity = untag_fixnum_fast(array->capacity);
|
||||||
|
for(i = 0; i < capacity; i++)
|
||||||
copy_object((void*)AREF(array,i));
|
copy_object((void*)AREF(array,i));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CELL header;
|
CELL header;
|
||||||
/* untagged */
|
/* tagged */
|
||||||
CELL capacity;
|
CELL capacity;
|
||||||
} F_ARRAY;
|
} F_ARRAY;
|
||||||
|
|
||||||
INLINE F_ARRAY* untag_array(CELL tagged)
|
INLINE F_ARRAY* untag_array(CELL tagged)
|
||||||
{
|
{
|
||||||
/* type_check(ARRAY_TYPE,tagged); */
|
type_check(ARRAY_TYPE,tagged);
|
||||||
return (F_ARRAY*)UNTAG(tagged); /* FIXME */
|
return (F_ARRAY*)UNTAG(tagged);
|
||||||
}
|
}
|
||||||
|
|
||||||
F_ARRAY* allot_array(CELL type, CELL capacity);
|
F_ARRAY* allot_array(CELL type, CELL capacity);
|
||||||
F_ARRAY* array(CELL capacity, CELL fill);
|
F_ARRAY* array(CELL capacity, CELL fill);
|
||||||
|
void primitive_array(void);
|
||||||
F_ARRAY* grow_array(F_ARRAY* array, CELL capacity, CELL fill);
|
F_ARRAY* grow_array(F_ARRAY* array, CELL capacity, CELL fill);
|
||||||
void primitive_grow_array(void);
|
void primitive_grow_array(void);
|
||||||
F_ARRAY* shrink_array(F_ARRAY* array, CELL capacity);
|
F_ARRAY* shrink_array(F_ARRAY* array, CELL capacity);
|
||||||
|
@ -19,7 +20,7 @@ F_ARRAY* shrink_array(F_ARRAY* array, CELL capacity);
|
||||||
#define AREF(array,index) ((CELL)(array) + sizeof(F_ARRAY) + (index) * CELLS)
|
#define AREF(array,index) ((CELL)(array) + sizeof(F_ARRAY) + (index) * CELLS)
|
||||||
|
|
||||||
#define ASIZE(pointer) align8(sizeof(F_ARRAY) + \
|
#define ASIZE(pointer) align8(sizeof(F_ARRAY) + \
|
||||||
((F_ARRAY*)(pointer))->capacity * CELLS)
|
untag_fixnum_fast(((F_ARRAY*)(pointer))->capacity) * CELLS)
|
||||||
|
|
||||||
void fixup_array(F_ARRAY* array);
|
void fixup_array(F_ARRAY* array);
|
||||||
void collect_array(F_ARRAY* array);
|
void collect_array(F_ARRAY* array);
|
||||||
|
|
|
@ -135,6 +135,7 @@ typedef unsigned char BYTE;
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "primitives.h"
|
#include "primitives.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
#include "hashtable.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "relocate.h"
|
#include "relocate.h"
|
||||||
|
|
|
@ -71,6 +71,9 @@ INLINE void collect_object(CELL scan)
|
||||||
case ARRAY_TYPE:
|
case ARRAY_TYPE:
|
||||||
collect_array((F_ARRAY*)scan);
|
collect_array((F_ARRAY*)scan);
|
||||||
break;
|
break;
|
||||||
|
case HASHTABLE_TYPE:
|
||||||
|
collect_hashtable((F_HASHTABLE*)scan);
|
||||||
|
break;
|
||||||
case VECTOR_TYPE:
|
case VECTOR_TYPE:
|
||||||
collect_vector((F_VECTOR*)scan);
|
collect_vector((F_VECTOR*)scan);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -27,6 +27,9 @@ INLINE void copy_object(CELL* handle)
|
||||||
if(tag == FIXNUM_TYPE)
|
if(tag == FIXNUM_TYPE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(headerp(pointer))
|
||||||
|
critical_error("Asked to copy header",pointer);
|
||||||
|
|
||||||
header = get(UNTAG(pointer));
|
header = get(UNTAG(pointer));
|
||||||
if(TAG(header) == GC_COLLECTED)
|
if(TAG(header) == GC_COLLECTED)
|
||||||
newpointer = UNTAG(header);
|
newpointer = UNTAG(header);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "factor.h"
|
||||||
|
|
||||||
|
F_HASHTABLE* hashtable(F_FIXNUM capacity)
|
||||||
|
{
|
||||||
|
F_HASHTABLE* hash;
|
||||||
|
if(capacity < 0)
|
||||||
|
general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
|
||||||
|
hash = allot_object(HASHTABLE_TYPE,sizeof(F_VECTOR));
|
||||||
|
hash->count = tag_fixnum(0);
|
||||||
|
hash->array = tag_object(array(capacity,F));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void primitive_hashtable(void)
|
||||||
|
{
|
||||||
|
maybe_garbage_collection();
|
||||||
|
drepl(tag_object(hashtable(to_fixnum(dpeek()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void primitive_to_hashtable(void)
|
||||||
|
{
|
||||||
|
type_check(HASHTABLE_TYPE,dpeek());
|
||||||
|
}
|
||||||
|
|
||||||
|
void fixup_hashtable(F_HASHTABLE* hashtable)
|
||||||
|
{
|
||||||
|
data_fixup(&hashtable->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
void collect_hashtable(F_HASHTABLE* hashtable)
|
||||||
|
{
|
||||||
|
copy_object(&hashtable->array);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
typedef struct {
|
||||||
|
/* always tag_header(HASHTABLE_TYPE) */
|
||||||
|
CELL header;
|
||||||
|
/* tagged */
|
||||||
|
CELL count;
|
||||||
|
/* tagged */
|
||||||
|
CELL array;
|
||||||
|
} F_HASHTABLE;
|
||||||
|
|
||||||
|
F_HASHTABLE* hashtable(F_FIXNUM capacity);
|
||||||
|
|
||||||
|
void primitive_hashtable(void);
|
||||||
|
void primitive_to_hashtable(void);
|
||||||
|
void fixup_hashtable(F_HASHTABLE* hashtable);
|
||||||
|
void collect_hashtable(F_HASHTABLE* hashtable);
|
|
@ -168,11 +168,14 @@ void* primitives[] = {
|
||||||
primitive_to_vector,
|
primitive_to_vector,
|
||||||
primitive_to_string,
|
primitive_to_string,
|
||||||
primitive_to_word,
|
primitive_to_word,
|
||||||
|
primitive_to_hashtable,
|
||||||
primitive_slot,
|
primitive_slot,
|
||||||
primitive_set_slot,
|
primitive_set_slot,
|
||||||
primitive_integer_slot,
|
primitive_integer_slot,
|
||||||
primitive_set_integer_slot,
|
primitive_set_integer_slot,
|
||||||
primitive_grow_array
|
primitive_grow_array,
|
||||||
|
primitive_hashtable,
|
||||||
|
primitive_array
|
||||||
};
|
};
|
||||||
|
|
||||||
CELL primitive_to_xt(CELL primitive)
|
CELL primitive_to_xt(CELL primitive)
|
||||||
|
|
|
@ -10,6 +10,9 @@ void relocate_object(CELL relocating)
|
||||||
case ARRAY_TYPE:
|
case ARRAY_TYPE:
|
||||||
fixup_array((F_ARRAY*)relocating);
|
fixup_array((F_ARRAY*)relocating);
|
||||||
break;
|
break;
|
||||||
|
case HASHTABLE_TYPE:
|
||||||
|
fixup_hashtable((F_HASHTABLE*)relocating);
|
||||||
|
break;
|
||||||
case VECTOR_TYPE:
|
case VECTOR_TYPE:
|
||||||
fixup_vector((F_VECTOR*)relocating);
|
fixup_vector((F_VECTOR*)relocating);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -83,7 +83,7 @@ typedef long bignum_length_type;
|
||||||
#define BIGNUM_START_PTR(bignum) \
|
#define BIGNUM_START_PTR(bignum) \
|
||||||
((BIGNUM_TO_POINTER (bignum)) + 1)
|
((BIGNUM_TO_POINTER (bignum)) + 1)
|
||||||
|
|
||||||
#define BIGNUM_LENGTH(bignum) ((bignum)->capacity - 1)
|
#define BIGNUM_LENGTH(bignum) (untag_fixnum_fast((bignum)->capacity) - 1)
|
||||||
|
|
||||||
#define BIGNUM_NEGATIVE_P(bignum) (get(AREF(bignum,0)) != 0)
|
#define BIGNUM_NEGATIVE_P(bignum) (get(AREF(bignum,0)) != 0)
|
||||||
#define BIGNUM_SET_NEGATIVE_P(bignum,neg) put(AREF(bignum,0),neg)
|
#define BIGNUM_SET_NEGATIVE_P(bignum,neg) put(AREF(bignum,0),neg)
|
||||||
|
|
|
@ -81,7 +81,7 @@ F_VECTOR* stack_to_vector(CELL bottom, CELL top)
|
||||||
F_VECTOR* v = vector(depth);
|
F_VECTOR* v = vector(depth);
|
||||||
F_ARRAY* a = untag_array(v->array);
|
F_ARRAY* a = untag_array(v->array);
|
||||||
memcpy(a + 1,(void*)bottom,depth * CELLS);
|
memcpy(a + 1,(void*)bottom,depth * CELLS);
|
||||||
v->top = depth;
|
v->top = tag_fixnum(depth);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ void primitive_callstack(void)
|
||||||
CELL vector_to_stack(F_VECTOR* vector, CELL bottom)
|
CELL vector_to_stack(F_VECTOR* vector, CELL bottom)
|
||||||
{
|
{
|
||||||
CELL start = bottom;
|
CELL start = bottom;
|
||||||
CELL len = vector->top * CELLS;
|
CELL len = untag_fixnum_fast(vector->top) * CELLS;
|
||||||
memcpy((void*)start,untag_array(vector->array) + 1,len);
|
memcpy((void*)start,untag_array(vector->array) + 1,len);
|
||||||
return start + len - CELLS;
|
return start + len - CELLS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,9 @@ CELL untagged_object_size(CELL pointer)
|
||||||
case BIGNUM_TYPE:
|
case BIGNUM_TYPE:
|
||||||
size = ASIZE(pointer);
|
size = ASIZE(pointer);
|
||||||
break;
|
break;
|
||||||
|
case HASHTABLE_TYPE:
|
||||||
|
size = sizeof(F_HASHTABLE);
|
||||||
|
break;
|
||||||
case VECTOR_TYPE:
|
case VECTOR_TYPE:
|
||||||
size = sizeof(F_VECTOR);
|
size = sizeof(F_VECTOR);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -27,6 +27,7 @@ CELL T;
|
||||||
#define F_TYPE 9
|
#define F_TYPE 9
|
||||||
#define F RETAG(0,OBJECT_TYPE)
|
#define F RETAG(0,OBJECT_TYPE)
|
||||||
|
|
||||||
|
#define HASHTABLE_TYPE 10
|
||||||
#define VECTOR_TYPE 11
|
#define VECTOR_TYPE 11
|
||||||
#define STRING_TYPE 12
|
#define STRING_TYPE 12
|
||||||
#define SBUF_TYPE 13
|
#define SBUF_TYPE 13
|
||||||
|
|
|
@ -6,7 +6,7 @@ F_VECTOR* vector(F_FIXNUM capacity)
|
||||||
if(capacity < 0)
|
if(capacity < 0)
|
||||||
general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
|
general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
|
||||||
vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
|
vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
|
||||||
vector->top = 0;
|
vector->top = tag_fixnum(0);
|
||||||
vector->array = tag_object(array(capacity,F));
|
vector->array = tag_object(array(capacity,F));
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* always tag_header(VECTOR_TYPE) */
|
/* always tag_header(VECTOR_TYPE) */
|
||||||
CELL header;
|
CELL header;
|
||||||
/* untagged */
|
/* tagged */
|
||||||
CELL top;
|
CELL top;
|
||||||
/* tagged */
|
/* tagged */
|
||||||
CELL array;
|
CELL array;
|
||||||
|
|
Loading…
Reference in New Issue