Merge branch 'master' of git://factorcode.org/git/factor

db4
Slava Pestov 2009-08-25 19:39:24 -05:00
commit fb1693bf1d
15 changed files with 264 additions and 239 deletions

View File

@ -4,4 +4,9 @@ USING: help.syntax help.markup byte-arrays alien.c-types ;
ARTICLE: "c-arrays" "C arrays" ARTICLE: "c-arrays" "C arrays"
"C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "." "C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "."
$nl $nl
"C type specifiers for array types are documented in " { $link "c-types-specs" } "." ; "C type specifiers for array types are documented in " { $link "c-types-specs" } "."
$nl
"Specialized sequences are provided for accessing memory as an array of primitive type values. These sequences are implemented in the " { $vocab-link "specialized-arrays" } " and " { $vocab-link "specialized-arrays.direct" } " vocabulary sets. They can also be loaded and constructed through their primitive C types:"
{ $subsection require-c-type-arrays }
{ $subsection <c-type-array> }
{ $subsection <c-type-direct-array> } ;

View File

@ -1,7 +1,7 @@
IN: alien.c-types IN: alien.c-types
USING: alien help.syntax help.markup libc kernel.private USING: alien help.syntax help.markup libc kernel.private
byte-arrays math strings hashtables alien.syntax alien.strings sequences byte-arrays math strings hashtables alien.syntax alien.strings sequences
io.encodings.string debugger destructors ; io.encodings.string debugger destructors vocabs.loader ;
HELP: <c-type> HELP: <c-type>
{ $values { "type" hashtable } } { $values { "type" hashtable } }
@ -128,6 +128,21 @@ HELP: malloc-string
} }
} ; } ;
HELP: require-c-type-arrays
{ $values { "c-type" "a C type" } }
{ $description { $link require } "s any unloaded vocabularies needed to construct a specialized array or direct array of " { $snippet "c-type" } " using the " { $link <c-type-array> } " or " { $link <c-type-direct-array> } " vocabularies." }
{ $notes "This word must be called inside a compilation unit. See the " { $vocab-link "specialized-arrays" } " and " { $vocab-link "specialized-arrays.direct" } " vocabulary sets for details on the underlying sequence types loaded." } ;
HELP: <c-type-array>
{ $values { "len" integer } { "c-type" "a C type" } { "array" "a specialized array" } }
{ $description "Constructs a new specialized array of length " { $snippet "len" } " and element type " { $snippet "c-type" } "." }
{ $notes "The appropriate specialized array vocabulary must be loaded; otherwise, a " { $link specialized-array-vocab-not-loaded } " error will be thrown. The vocabulary can be loaded with a " { $link POSTPONE: USING: } " form as usual, or with the " { $link require-c-type-arrays } " word. See the " { $vocab-link "specialized-arrays" } " vocabulary set for details on the underlying sequence type constructed." } ;
HELP: <c-type-direct-array>
{ $values { "alien" c-ptr } { "len" integer } { "c-type" "a C type" } { "array" "a specialized direct array" } }
{ $description "Constructs a new specialized array of length " { $snippet "len" } " and element type " { $snippet "c-type" } " over the range of memory referenced by " { $snippet "alien" } "." }
{ $notes "The appropriate direct specialized array vocabulary must be loaded; otherwise, a " { $link specialized-array-vocab-not-loaded } " error will be thrown. The vocabulary can be loaded with a " { $link POSTPONE: USING: } " form as usual, or with the " { $link require-c-type-arrays } " word. See the " { $vocab-link "specialized-arrays.direct" } " vocabulary set for details on the underlying sequence type constructed." } ;
ARTICLE: "c-strings" "C strings" ARTICLE: "c-strings" "C strings"
"C string types are arrays with shape " { $snippet "{ \"char*\" encoding }" } ", where " { $snippet "encoding" } " is an encoding descriptor. The type " { $snippet "\"char*\"" } " is an alias for " { $snippet "{ \"char*\" utf8 }" } ". See " { $link "encodings-descriptors" } " for information about encoding descriptors." "C string types are arrays with shape " { $snippet "{ \"char*\" encoding }" } ", where " { $snippet "encoding" } " is an encoding descriptor. The type " { $snippet "\"char*\"" } " is an alias for " { $snippet "{ \"char*\" utf8 }" } ". See " { $link "encodings-descriptors" } " for information about encoding descriptors."
$nl $nl

View File

@ -5,7 +5,7 @@ namespaces make parser sequences strings words splitting math.parser
cpu.architecture alien alien.accessors alien.strings quotations cpu.architecture alien alien.accessors alien.strings quotations
layouts system compiler.units io io.files io.encodings.binary layouts system compiler.units io io.files io.encodings.binary
io.streams.memory accessors combinators effects continuations fry io.streams.memory accessors combinators effects continuations fry
classes ; classes vocabs vocabs.loader ;
IN: alien.c-types IN: alien.c-types
DEFER: <int> DEFER: <int>
@ -27,7 +27,12 @@ TUPLE: c-type < abstract-c-type
boxer boxer
unboxer unboxer
{ rep initial: int-rep } { rep initial: int-rep }
stack-align? ; stack-align?
array-class
array-constructor
direct-array-class
direct-array-constructor
sequence-mixin-class ;
: <c-type> ( -- type ) : <c-type> ( -- type )
\ c-type new ; \ c-type new ;
@ -71,6 +76,55 @@ M: string c-type ( name -- type )
] ?if ] ?if
] if ; ] if ;
: ?require-word ( word/pair -- )
dup word? [ drop ] [ first require ] ?if ;
GENERIC: require-c-type-arrays ( c-type -- )
M: object require-c-type-arrays
drop ;
M: c-type require-c-type-arrays
[ array-class>> ?require-word ]
[ sequence-mixin-class>> ?require-word ]
[ direct-array-class>> ?require-word ] tri ;
M: string require-c-type-arrays
c-type require-c-type-arrays ;
M: array require-c-type-arrays
first c-type require-c-type-arrays ;
ERROR: specialized-array-vocab-not-loaded vocab word ;
GENERIC: c-type-array-constructor ( c-type -- word ) foldable
M: string c-type-array-constructor
c-type c-type-array-constructor ;
M: array c-type-array-constructor
first c-type c-type-array-constructor ;
M: c-type c-type-array-constructor
array-constructor>> dup word?
[ first2 specialized-array-vocab-not-loaded ] unless ;
GENERIC: c-type-direct-array-constructor ( c-type -- word ) foldable
M: string c-type-direct-array-constructor
c-type c-type-direct-array-constructor ;
M: array c-type-direct-array-constructor
first c-type c-type-direct-array-constructor ;
M: c-type c-type-direct-array-constructor
direct-array-constructor>> dup word?
[ first2 specialized-array-vocab-not-loaded ] unless ;
GENERIC: <c-type-array> ( len c-type -- array )
M: object <c-type-array>
c-type-array-constructor execute( len -- array ) ; inline
GENERIC: <c-type-direct-array> ( alien len c-type -- array )
M: object <c-type-direct-array>
c-type-direct-array-constructor execute( alien len -- array ) ; inline
GENERIC: c-type-class ( name -- class ) GENERIC: c-type-class ( name -- class )
M: abstract-c-type c-type-class class>> ; M: abstract-c-type c-type-class class>> ;
@ -293,6 +347,36 @@ M: long-long-type box-return ( type -- )
: if-void ( type true false -- ) : if-void ( type true false -- )
pick "void" = [ drop nip call ] [ nip call ] if ; inline pick "void" = [ drop nip call ] [ nip call ] if ; inline
: ?lookup ( vocab word -- word/pair )
over vocab [ swap lookup ] [ 2array ] if ;
: set-array-class* ( c-type vocab-stem type-stem -- c-type )
{
[
[ "specialized-arrays." prepend ]
[ "-array" append ] bi* ?lookup >>array-class
]
[
[ "specialized-arrays." prepend ]
[ "<" "-array>" surround ] bi* ?lookup >>array-constructor
]
[
[ "specialized-arrays." prepend ]
[ "-sequence" append ] bi* ?lookup >>sequence-mixin-class
]
[
[ "specialized-arrays.direct." prepend ]
[ "direct-" "-array" surround ] bi* ?lookup >>direct-array-class
]
[
[ "specialized-arrays.direct." prepend ]
[ "<direct-" "-array>" surround ] bi* ?lookup >>direct-array-constructor
]
} 2cleave ;
: set-array-class ( c-type stem -- c-type )
dup set-array-class* ;
CONSTANT: primitive-types CONSTANT: primitive-types
{ {
"char" "uchar" "char" "uchar"
@ -315,6 +399,7 @@ CONSTANT: primitive-types
[ >c-ptr ] >>unboxer-quot [ >c-ptr ] >>unboxer-quot
"box_alien" >>boxer "box_alien" >>boxer
"alien_offset" >>unboxer "alien_offset" >>unboxer
"alien" "void*" set-array-class*
"void*" define-primitive-type "void*" define-primitive-type
<long-long-type> <long-long-type>
@ -326,6 +411,7 @@ CONSTANT: primitive-types
8 >>align 8 >>align
"box_signed_8" >>boxer "box_signed_8" >>boxer
"to_signed_8" >>unboxer "to_signed_8" >>unboxer
"longlong" set-array-class
"longlong" define-primitive-type "longlong" define-primitive-type
<long-long-type> <long-long-type>
@ -337,6 +423,7 @@ CONSTANT: primitive-types
8 >>align 8 >>align
"box_unsigned_8" >>boxer "box_unsigned_8" >>boxer
"to_unsigned_8" >>unboxer "to_unsigned_8" >>unboxer
"ulonglong" set-array-class
"ulonglong" define-primitive-type "ulonglong" define-primitive-type
<c-type> <c-type>
@ -348,6 +435,7 @@ CONSTANT: primitive-types
bootstrap-cell >>align bootstrap-cell >>align
"box_signed_cell" >>boxer "box_signed_cell" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
"long" set-array-class
"long" define-primitive-type "long" define-primitive-type
<c-type> <c-type>
@ -359,6 +447,7 @@ CONSTANT: primitive-types
bootstrap-cell >>align bootstrap-cell >>align
"box_unsigned_cell" >>boxer "box_unsigned_cell" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
"ulong" set-array-class
"ulong" define-primitive-type "ulong" define-primitive-type
<c-type> <c-type>
@ -370,6 +459,7 @@ CONSTANT: primitive-types
4 >>align 4 >>align
"box_signed_4" >>boxer "box_signed_4" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
"int" set-array-class
"int" define-primitive-type "int" define-primitive-type
<c-type> <c-type>
@ -381,6 +471,7 @@ CONSTANT: primitive-types
4 >>align 4 >>align
"box_unsigned_4" >>boxer "box_unsigned_4" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
"uint" set-array-class
"uint" define-primitive-type "uint" define-primitive-type
<c-type> <c-type>
@ -392,6 +483,7 @@ CONSTANT: primitive-types
2 >>align 2 >>align
"box_signed_2" >>boxer "box_signed_2" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
"short" set-array-class
"short" define-primitive-type "short" define-primitive-type
<c-type> <c-type>
@ -403,6 +495,7 @@ CONSTANT: primitive-types
2 >>align 2 >>align
"box_unsigned_2" >>boxer "box_unsigned_2" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
"ushort" set-array-class
"ushort" define-primitive-type "ushort" define-primitive-type
<c-type> <c-type>
@ -414,6 +507,7 @@ CONSTANT: primitive-types
1 >>align 1 >>align
"box_signed_1" >>boxer "box_signed_1" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
"char" set-array-class
"char" define-primitive-type "char" define-primitive-type
<c-type> <c-type>
@ -425,6 +519,7 @@ CONSTANT: primitive-types
1 >>align 1 >>align
"box_unsigned_1" >>boxer "box_unsigned_1" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
"uchar" set-array-class
"uchar" define-primitive-type "uchar" define-primitive-type
<c-type> <c-type>
@ -434,6 +529,7 @@ CONSTANT: primitive-types
1 >>align 1 >>align
"box_boolean" >>boxer "box_boolean" >>boxer
"to_boolean" >>unboxer "to_boolean" >>unboxer
"bool" set-array-class
"bool" define-primitive-type "bool" define-primitive-type
<c-type> <c-type>
@ -447,6 +543,7 @@ CONSTANT: primitive-types
"to_float" >>unboxer "to_float" >>unboxer
single-float-rep >>rep single-float-rep >>rep
[ >float ] >>unboxer-quot [ >float ] >>unboxer-quot
"float" set-array-class
"float" define-primitive-type "float" define-primitive-type
<c-type> <c-type>
@ -460,9 +557,11 @@ CONSTANT: primitive-types
"to_double" >>unboxer "to_double" >>unboxer
double-float-rep >>rep double-float-rep >>rep
[ >float ] >>unboxer-quot [ >float ] >>unboxer-quot
"double" set-array-class
"double" define-primitive-type "double" define-primitive-type
"long" "ptrdiff_t" typedef "long" "ptrdiff_t" typedef
"long" "intptr_t" typedef "long" "intptr_t" typedef
"ulong" "size_t" typedef "ulong" "size_t" typedef
] with-compilation-unit ] with-compilation-unit

View File

@ -8,6 +8,7 @@ IN: specialized-arrays.direct.functor
FUNCTOR: define-direct-array ( T -- ) FUNCTOR: define-direct-array ( T -- )
A' IS ${T}-array A' IS ${T}-array
S IS ${T}-sequence
>A' IS >${T}-array >A' IS >${T}-array
<A'> IS <${A'}> <A'> IS <${A'}>
A'{ IS ${A'}{ A'{ IS ${A'}{
@ -31,6 +32,8 @@ M: A set-nth-unsafe underlying>> SET-NTH call ;
M: A like drop dup A instance? [ >A' ] unless ; M: A like drop dup A instance? [ >A' ] unless ;
M: A new-sequence drop <A'> ; M: A new-sequence drop <A'> ;
M: A byte-length length>> T heap-size * ;
M: A pprint-delims drop \ A'{ \ } ; M: A pprint-delims drop \ A'{ \ } ;
M: A >pprint-sequence ; M: A >pprint-sequence ;
@ -38,5 +41,11 @@ M: A >pprint-sequence ;
M: A pprint* pprint-object ; M: A pprint* pprint-object ;
INSTANCE: A sequence INSTANCE: A sequence
INSTANCE: A S
T c-type
\ A >>direct-array-class
\ <A> >>direct-array-constructor
drop
;FUNCTOR ;FUNCTOR

View File

@ -16,6 +16,7 @@ M: bad-byte-array-length summary
FUNCTOR: define-array ( T -- ) FUNCTOR: define-array ( T -- )
A DEFINES-CLASS ${T}-array A DEFINES-CLASS ${T}-array
S DEFINES-CLASS ${T}-sequence
<A> DEFINES <${A}> <A> DEFINES <${A}>
(A) DEFINES (${A}) (A) DEFINES (${A})
>A DEFINES >${A} >A DEFINES >${A}
@ -27,6 +28,8 @@ SET-NTH [ T dup c-setter array-accessor ]
WHERE WHERE
MIXIN: S
TUPLE: A TUPLE: A
{ length array-capacity read-only } { length array-capacity read-only }
{ underlying byte-array read-only } ; { underlying byte-array read-only } ;
@ -73,7 +76,14 @@ M: A pprint* pprint-object ;
SYNTAX: A{ \ } [ >A ] parse-literal ; SYNTAX: A{ \ } [ >A ] parse-literal ;
INSTANCE: A sequence INSTANCE: A sequence
INSTANCE: A S
A T c-type-boxed-class specialize-vector-words A T c-type-boxed-class specialize-vector-words
T c-type
\ A >>array-class
\ <A> >>array-constructor
\ S >>sequence-mixin-class
drop
;FUNCTOR ;FUNCTOR

View File

@ -10,6 +10,7 @@ FUNCTOR: define-vector ( T -- )
V DEFINES-CLASS ${T}-vector V DEFINES-CLASS ${T}-vector
A IS ${T}-array A IS ${T}-array
S IS ${T}-sequence
<A> IS <${A}> <A> IS <${A}>
>V DEFERS >${V} >V DEFERS >${V}
@ -32,5 +33,6 @@ M: V pprint* pprint-object ;
SYNTAX: V{ \ } [ >V ] parse-literal ; SYNTAX: V{ \ } [ >V ] parse-literal ;
INSTANCE: V growable INSTANCE: V growable
INSTANCE: V S
;FUNCTOR ;FUNCTOR

View File

@ -153,7 +153,7 @@ PRIVATE>
[ +live-wrappers+ get adjoin ] bi ; [ +live-wrappers+ get adjoin ] bi ;
: <com-wrapper> ( implementations -- wrapper ) : <com-wrapper> ( implementations -- wrapper )
com-wrapper new-disposable swap (make-callbacks) >>vtbls com-wrapper new-disposable swap (make-callbacks) >>callbacks
dup allocate-wrapper ; dup allocate-wrapper ;
M: com-wrapper dispose* M: com-wrapper dispose*

View File

@ -93,7 +93,7 @@ ALIAS: marshall-void* marshall-pointer
: primitive-marshaller ( type -- quot/f ) : primitive-marshaller ( type -- quot/f )
{ {
{ "bool" [ [ marshall-bool ] ] } { "bool" [ [ ] ] }
{ "boolean" [ [ marshall-bool ] ] } { "boolean" [ [ marshall-bool ] ] }
{ "char" [ [ marshall-primitive ] ] } { "char" [ [ marshall-primitive ] ] }
{ "uchar" [ [ marshall-primitive ] ] } { "uchar" [ [ marshall-primitive ] ] }
@ -179,7 +179,7 @@ ALIAS: marshall-void* marshall-pointer
: primitive-unmarshaller ( type -- quot/f ) : primitive-unmarshaller ( type -- quot/f )
{ {
{ "bool" [ [ unmarshall-bool ] ] } { "bool" [ [ ] ] }
{ "boolean" [ [ unmarshall-bool ] ] } { "boolean" [ [ unmarshall-bool ] ] }
{ "char" [ [ ] ] } { "char" [ [ ] ] }
{ "uchar" [ [ ] ] } { "uchar" [ [ ] ] }

View File

@ -9,8 +9,7 @@ C-LIBRARY: test
C-INCLUDE: <stdlib.h> C-INCLUDE: <stdlib.h>
C-INCLUDE: <string.h> C-INCLUDE: <string.h>
C-INCLUDE: <stdbool.h>
C-TYPEDEF: char bool
CM-FUNCTION: void outarg1 ( int* a ) CM-FUNCTION: void outarg1 ( int* a )
*a += 2; *a += 2;

View File

@ -1,72 +0,0 @@
! (c)Joe Groff bsd license
USING: alien arrays classes help.markup help.syntax kernel math
specialized-arrays.direct ;
IN: classes.c-types
HELP: c-type-class
{ $class-description "This metaclass encompasses the " { $link "classes.c-types" } "." } ;
HELP: char
{ $class-description "A signed one-byte integer quantity." } ;
HELP: direct-array-of
{ $values
{ "alien" c-ptr } { "len" integer } { "class" c-type-class }
{ "array" "a direct array" }
}
{ $description "Constructs one of the " { $link "specialized-arrays.direct" } " over " { $snippet "len" } " elements of type " { $snippet "class" } " located at the referenced location in raw memory." } ;
HELP: int
{ $class-description "A signed four-byte integer quantity." } ;
HELP: long
{ $class-description "A signed integer quantity. On 64-bit Unix platforms, this is an eight-byte type; on Windows and on 32-bit Unix platforms, it is four bytes." } ;
HELP: longlong
{ $class-description "A signed eight-byte integer quantity." } ;
HELP: short
{ $class-description "A signed two-byte integer quantity." } ;
HELP: single-complex
{ $class-description "A single-precision complex floating point quantity." } ;
HELP: single-float
{ $class-description "A single-precision floating point quantity." } ;
HELP: uchar
{ $class-description "An unsigned one-byte integer quantity." } ;
HELP: uint
{ $class-description "An unsigned four-byte integer quantity." } ;
HELP: ulong
{ $class-description "An unsigned integer quantity. On 64-bit Unix platforms, this is an eight-byte type; on Windows and on 32-bit Unix platforms, it is four bytes." } ;
HELP: ulonglong
{ $class-description "An unsigned eight-byte integer quantity." } ;
HELP: ushort
{ $class-description "An unsigned two-byte integer quantity." } ;
ARTICLE: "classes.c-types" "C type classes"
"The " { $vocab-link "classes.c-types" } " vocabulary defines Factor classes that correspond to C types in the FFI."
{ $subsection char }
{ $subsection uchar }
{ $subsection short }
{ $subsection ushort }
{ $subsection int }
{ $subsection uint }
{ $subsection long }
{ $subsection ulong }
{ $subsection longlong }
{ $subsection ulonglong }
{ $subsection single-float }
{ $subsection float }
{ $subsection single-complex }
{ $subsection complex }
{ $subsection pinned-c-ptr }
"The vocabulary also provides a word for constructing " { $link "specialized-arrays.direct" } " of C types over raw memory:"
{ $subsection direct-array-of } ;
ABOUT: "classes.c-types"

View File

@ -1,118 +0,0 @@
! (c)Joe Groff bsd license
USING: alien alien.c-types classes classes.predicate kernel
math math.bitwise math.order namespaces sequences words
specialized-arrays.direct.alien
specialized-arrays.direct.bool
specialized-arrays.direct.char
specialized-arrays.direct.complex-double
specialized-arrays.direct.complex-float
specialized-arrays.direct.double
specialized-arrays.direct.float
specialized-arrays.direct.int
specialized-arrays.direct.long
specialized-arrays.direct.longlong
specialized-arrays.direct.short
specialized-arrays.direct.uchar
specialized-arrays.direct.uint
specialized-arrays.direct.ulong
specialized-arrays.direct.ulonglong
specialized-arrays.direct.ushort ;
IN: classes.c-types
PREDICATE: char < fixnum
HEX: -80 HEX: 7f between? ;
PREDICATE: uchar < fixnum
HEX: 0 HEX: ff between? ;
PREDICATE: short < fixnum
HEX: -8000 HEX: 7fff between? ;
PREDICATE: ushort < fixnum
HEX: 0 HEX: ffff between? ;
PREDICATE: int < integer
HEX: -8000,0000 HEX: 7fff,ffff between? ;
PREDICATE: uint < integer
HEX: 0 HEX: ffff,ffff between? ;
PREDICATE: longlong < integer
HEX: -8000,0000,0000,0000 HEX: 7fff,ffff,ffff,ffff between? ;
PREDICATE: ulonglong < integer
HEX: 0 HEX: ffff,ffff,ffff,ffff between? ;
UNION: single-float float ;
UNION: single-complex complex ;
SYMBOLS: long ulong long-bits ;
<<
"long" heap-size 8 =
[
\ long integer [ HEX: -8000,0000,0000,0000 HEX: 7fff,ffff,ffff,ffff between? ] define-predicate-class
\ ulong integer [ HEX: 0 HEX: ffff,ffff,ffff,ffff between? ] define-predicate-class
64 \ long-bits set-global
] [
\ long integer [ HEX: -8000,0000 HEX: 7fff,ffff between? ] define-predicate-class
\ ulong integer [ HEX: 0 HEX: ffff,ffff between? ] define-predicate-class
32 \ long-bits set-global
] if
>>
: set-class-c-type ( class initial c-type <direct-array> -- )
[ "initial-value" set-word-prop ]
[ c-type "class-c-type" set-word-prop ]
[ "class-direct-array" set-word-prop ] tri-curry* tri ;
: class-c-type ( class -- c-type )
"class-c-type" word-prop ;
: class-direct-array ( class -- <direct-array> )
"class-direct-array" word-prop ;
\ f f "void*" \ <direct-void*-array> set-class-c-type
pinned-c-ptr f "void*" \ <direct-void*-array> set-class-c-type
boolean f "bool" \ <direct-bool-array> set-class-c-type
char 0 "char" \ <direct-char-array> set-class-c-type
uchar 0 "uchar" \ <direct-uchar-array> set-class-c-type
short 0 "short" \ <direct-short-array> set-class-c-type
ushort 0 "ushort" \ <direct-ushort-array> set-class-c-type
int 0 "int" \ <direct-int-array> set-class-c-type
uint 0 "uint" \ <direct-uint-array> set-class-c-type
long 0 "long" \ <direct-long-array> set-class-c-type
ulong 0 "ulong" \ <direct-ulong-array> set-class-c-type
longlong 0 "longlong" \ <direct-longlong-array> set-class-c-type
ulonglong 0 "ulonglong" \ <direct-ulonglong-array> set-class-c-type
float 0.0 "double" \ <direct-double-array> set-class-c-type
single-float 0.0 "float" \ <direct-float-array> set-class-c-type
complex C{ 0.0 0.0 } "complex-double" \ <direct-complex-double-array> set-class-c-type
single-complex C{ 0.0 0.0 } "complex-float" \ <direct-complex-float-array> set-class-c-type
char [ 8 bits 8 >signed ] "coercer" set-word-prop
uchar [ 8 bits ] "coercer" set-word-prop
short [ 16 bits 16 >signed ] "coercer" set-word-prop
ushort [ 16 bits ] "coercer" set-word-prop
int [ 32 bits 32 >signed ] "coercer" set-word-prop
uint [ 32 bits ] "coercer" set-word-prop
long [ [ bits ] [ >signed ] ] long-bits get-global prefix "coercer" set-word-prop
ulong [ bits ] long-bits get-global prefix "coercer" set-word-prop
longlong [ 64 bits 64 >signed ] "coercer" set-word-prop
ulonglong [ 64 bits ] "coercer" set-word-prop
PREDICATE: c-type-class < class
"class-c-type" word-prop ;
GENERIC: direct-array-of ( alien len class -- array ) inline
M: c-type-class direct-array-of
class-direct-array execute( alien len -- array ) ; inline
M: c-type-class c-type class-c-type ;
M: c-type-class c-type-align class-c-type c-type-align ;
M: c-type-class c-type-getter class-c-type c-type-getter ;
M: c-type-class c-type-setter class-c-type c-type-setter ;
M: c-type-class c-type-boxer-quot class-c-type c-type-boxer-quot ;
M: c-type-class c-type-unboxer-quot class-c-type c-type-unboxer-quot ;
M: c-type-class heap-size class-c-type heap-size ;

View File

@ -1,7 +1,7 @@
! (c)Joe Groff bsd license ! (c)Joe Groff bsd license
USING: accessors assocs classes classes.struct kernel math USING: accessors assocs classes classes.struct combinators
prettyprint.backend prettyprint.custom prettyprint.sections kernel math prettyprint.backend prettyprint.custom
see.private sequences words ; prettyprint.sections see.private sequences words ;
IN: classes.struct.prettyprint IN: classes.struct.prettyprint
<PRIVATE <PRIVATE
@ -14,11 +14,21 @@ IN: classes.struct.prettyprint
: struct>assoc ( struct -- assoc ) : struct>assoc ( struct -- assoc )
[ class struct-slots ] [ struct-slot-values ] bi zip filter-tuple-assoc ; [ class struct-slots ] [ struct-slot-values ] bi zip filter-tuple-assoc ;
: pprint-struct-slot ( slot -- )
<flow \ { pprint-word
{
[ name>> text ]
[ c-type>> text ]
[ read-only>> [ \ read-only pprint-word ] when ]
[ initial>> [ \ initial: pprint-word pprint* ] when* ]
} cleave
\ } pprint-word block> ;
PRIVATE> PRIVATE>
M: struct-class see-class* M: struct-class see-class*
<colon dup struct-definer-word pprint-word dup pprint-word <colon dup struct-definer-word pprint-word dup pprint-word
<block struct-slots [ pprint-slot ] each <block struct-slots [ pprint-struct-slot ] each
block> pprint-; block> ; block> pprint-; block> ;
M: struct pprint-delims M: struct pprint-delims

View File

@ -24,7 +24,7 @@ HELP: STRUCT:
{ $description "Defines a new " { $link struct } " type. The syntax is nearly identical to " { $link POSTPONE: TUPLE: } "; however, there are some additional restrictions on struct types:" { $description "Defines a new " { $link struct } " type. The syntax is nearly identical to " { $link POSTPONE: TUPLE: } "; however, there are some additional restrictions on struct types:"
{ $list { $list
{ "Struct classes cannot have a superclass defined." } { "Struct classes cannot have a superclass defined." }
{ "The slots of a struct must all have a type declared. The type must be either another struct class, or one of the " { $link "classes.c-types" } "." } { "The slots of a struct must all have a type declared. The type must be a C type." }
{ { $link read-only } " slots on structs are not enforced, though they may be declared." } { { $link read-only } " slots on structs are not enforced, though they may be declared." }
} } ; } } ;

View File

@ -1,19 +1,36 @@
! (c)Joe Groff bsd license ! (c)Joe Groff bsd license
USING: accessors alien.c-types alien.structs.fields classes.c-types USING: accessors alien.c-types alien.libraries
classes.struct combinators io.streams.string kernel libc literals math alien.structs.fields alien.syntax classes.struct combinators
multiline namespaces prettyprint prettyprint.config see tools.test ; destructors io.encodings.utf8 io.pathnames io.streams.string
kernel libc literals math multiline namespaces prettyprint
prettyprint.config see system tools.test ;
IN: classes.struct.tests IN: classes.struct.tests
<<
: libfactor-ffi-tests-path ( -- string )
"resource:" (normalize-path)
{
{ [ os winnt? ] [ "libfactor-ffi-test.dll" ] }
{ [ os macosx? ] [ "libfactor-ffi-test.dylib" ] }
{ [ os unix? ] [ "libfactor-ffi-test.so" ] }
} cond append-path ;
"f-cdecl" libfactor-ffi-tests-path "cdecl" add-library
"f-stdcall" libfactor-ffi-tests-path "stdcall" add-library
>>
STRUCT: struct-test-foo STRUCT: struct-test-foo
{ x char } { x char }
{ y int initial: 123 } { y int initial: 123 }
{ z boolean } ; { z bool } ;
STRUCT: struct-test-bar STRUCT: struct-test-bar
{ w ushort initial: HEX: ffff } { w ushort initial: HEX: ffff }
{ foo struct-test-foo } ; { foo struct-test-foo } ;
[ 12 ] [ struct-test-foo heap-size ] unit-test [ 12 ] [ struct-test-foo heap-size ] unit-test
[ 12 ] [ struct-test-foo <struct> byte-length ] unit-test
[ 16 ] [ struct-test-bar heap-size ] unit-test [ 16 ] [ struct-test-bar heap-size ] unit-test
[ 123 ] [ struct-test-foo <struct> y>> ] unit-test [ 123 ] [ struct-test-foo <struct> y>> ] unit-test
[ 123 ] [ struct-test-bar <struct> foo>> y>> ] unit-test [ 123 ] [ struct-test-bar <struct> foo>> y>> ] unit-test
@ -32,13 +49,24 @@ STRUCT: struct-test-bar
[ 7654 ] [ S{ struct-test-foo { y 7654 } } y>> ] unit-test [ 7654 ] [ S{ struct-test-foo { y 7654 } } y>> ] unit-test
UNION-STRUCT: struct-test-float-and-bits UNION-STRUCT: struct-test-float-and-bits
{ f single-float } { f float }
{ bits uint } ; { bits uint } ;
[ 1.0 ] [ struct-test-float-and-bits <struct> 1.0 float>bits >>bits f>> ] unit-test [ 1.0 ] [ struct-test-float-and-bits <struct> 1.0 float>bits >>bits f>> ] unit-test
[ 4 ] [ struct-test-float-and-bits heap-size ] unit-test [ 4 ] [ struct-test-float-and-bits heap-size ] unit-test
[ ] [ struct-test-foo malloc-struct free ] unit-test [ ] [ [ struct-test-foo malloc-struct &free drop ] with-destructors ] unit-test
STRUCT: struct-test-string-ptr
{ x char* } ;
[ "hello world" ] [
[
struct-test-string-ptr <struct>
"hello world" utf8 malloc-string &free >>x
x>>
] with-destructors
] unit-test
[ "S{ struct-test-foo { y 7654 } }" ] [ "S{ struct-test-foo { y 7654 } }" ]
[ [
@ -54,18 +82,17 @@ UNION-STRUCT: struct-test-float-and-bits
with-variable with-variable
] unit-test ] unit-test
[ <" USING: classes.c-types classes.struct kernel ; [ <" USING: classes.struct ;
IN: classes.struct.tests IN: classes.struct.tests
STRUCT: struct-test-foo STRUCT: struct-test-foo
{ x char initial: 0 } { y int initial: 123 } { x char initial: 0 } { y int initial: 123 } { z bool } ;
{ z boolean initial: f } ;
"> ] "> ]
[ [ struct-test-foo see ] with-string-writer ] unit-test [ [ struct-test-foo see ] with-string-writer ] unit-test
[ <" USING: classes.c-types classes.struct ; [ <" USING: classes.struct ;
IN: classes.struct.tests IN: classes.struct.tests
UNION-STRUCT: struct-test-float-and-bits UNION-STRUCT: struct-test-float-and-bits
{ f single-float initial: 0.0 } { bits uint initial: 0 } ; { f float initial: 0.0 } { bits uint initial: 0 } ;
"> ] "> ]
[ [ struct-test-float-and-bits see ] with-string-writer ] unit-test [ [ struct-test-float-and-bits see ] with-string-writer ] unit-test
@ -73,21 +100,21 @@ UNION-STRUCT: struct-test-float-and-bits
T{ field-spec T{ field-spec
{ name "x" } { name "x" }
{ offset 0 } { offset 0 }
{ type $[ char c-type ] } { type "char" }
{ reader x>> } { reader x>> }
{ writer (>>x) } { writer (>>x) }
} }
T{ field-spec T{ field-spec
{ name "y" } { name "y" }
{ offset 4 } { offset 4 }
{ type $[ int c-type ] } { type "int" }
{ reader y>> } { reader y>> }
{ writer (>>y) } { writer (>>y) }
} }
T{ field-spec T{ field-spec
{ name "z" } { name "z" }
{ offset 8 } { offset 8 }
{ type $[ boolean c-type ] } { type "bool" }
{ reader z>> } { reader z>> }
{ writer (>>z) } { writer (>>z) }
} }
@ -97,16 +124,24 @@ UNION-STRUCT: struct-test-float-and-bits
T{ field-spec T{ field-spec
{ name "f" } { name "f" }
{ offset 0 } { offset 0 }
{ type $[ single-float c-type ] } { type "float" }
{ reader f>> } { reader f>> }
{ writer (>>f) } { writer (>>f) }
} }
T{ field-spec T{ field-spec
{ name "bits" } { name "bits" }
{ offset 0 } { offset 0 }
{ type $[ uint c-type ] } { type "uint" }
{ reader bits>> } { reader bits>> }
{ writer (>>bits) } { writer (>>bits) }
} }
} ] [ "struct-test-float-and-bits" c-type fields>> ] unit-test } ] [ "struct-test-float-and-bits" c-type fields>> ] unit-test
STRUCT: struct-test-ffi-foo
{ x int }
{ y int } ;
LIBRARY: f-cdecl
FUNCTION: int ffi_test_11 ( int a, struct-test-ffi-foo b, int c ) ;
[ 14 ] [ 1 2 3 struct-test-ffi-foo <struct-boa> 4 ffi_test_11 ] unit-test

View File

@ -1,10 +1,11 @@
! (c)Joe Groff bsd license ! (c)Joe Groff bsd license
USING: accessors alien alien.c-types alien.structs alien.structs.fields arrays USING: accessors alien alien.c-types alien.structs alien.structs.fields arrays
byte-arrays classes classes.c-types classes.parser classes.tuple byte-arrays classes classes.parser classes.tuple
classes.tuple.parser classes.tuple.private combinators classes.tuple.parser classes.tuple.private combinators
combinators.smart fry generalizations generic.parser kernel combinators.smart fry generalizations generic.parser kernel
kernel.private libc macros make math math.order parser kernel.private lexer libc macros make math math.order parser
quotations sequences slots slots.private struct-arrays words ; quotations sequences slots slots.private struct-arrays
vectors words ;
FROM: slots => reader-word writer-word ; FROM: slots => reader-word writer-word ;
IN: classes.struct IN: classes.struct
@ -13,6 +14,9 @@ IN: classes.struct
TUPLE: struct TUPLE: struct
{ (underlying) c-ptr read-only } ; { (underlying) c-ptr read-only } ;
TUPLE: struct-slot-spec < slot-spec
c-type ;
PREDICATE: struct-class < tuple-class PREDICATE: struct-class < tuple-class
\ struct subclass-of? ; \ struct subclass-of? ;
@ -52,11 +56,11 @@ MACRO: <struct-boa> ( class -- quot: ( ... -- struct ) )
[ struct-slots [ initial>> ] map over length tail append ] keep ; [ struct-slots [ initial>> ] map over length tail append ] keep ;
: (reader-quot) ( slot -- quot ) : (reader-quot) ( slot -- quot )
[ class>> c-type-getter-boxer ] [ c-type>> c-type-getter-boxer ]
[ offset>> [ >c-ptr ] swap suffix ] bi prepend ; [ offset>> [ >c-ptr ] swap suffix ] bi prepend ;
: (writer-quot) ( slot -- quot ) : (writer-quot) ( slot -- quot )
[ class>> c-setter ] [ c-type>> c-setter ]
[ offset>> [ >c-ptr ] swap suffix ] bi prepend ; [ offset>> [ >c-ptr ] swap suffix ] bi prepend ;
: (boxer-quot) ( class -- quot ) : (boxer-quot) ( class -- quot )
@ -90,13 +94,17 @@ M: struct-class writer-quot
[ \ struct-slot-values create-method-in ] [ \ struct-slot-values create-method-in ]
[ struct-slot-values-quot ] bi define ; [ struct-slot-values-quot ] bi define ;
: (define-byte-length-method) ( class -- )
[ \ byte-length create-method-in ]
[ heap-size \ drop swap [ ] 2sequence ] bi define ;
! Struct as c-type ! Struct as c-type
: slot>field ( slot -- field ) : slot>field ( slot -- field )
field-spec new swap { field-spec new swap {
[ name>> >>name ] [ name>> >>name ]
[ offset>> >>offset ] [ offset>> >>offset ]
[ class>> c-type >>type ] [ c-type>> >>type ]
[ name>> reader-word >>reader ] [ name>> reader-word >>reader ]
[ name>> writer-word >>writer ] [ name>> writer-word >>writer ]
} cleave ; } cleave ;
@ -111,9 +119,12 @@ M: struct-class writer-quot
} cleave } cleave
(define-struct) (define-struct)
] [ ] [
[ name>> c-type ] {
[ (unboxer-quot) >>unboxer-quot ] [ name>> c-type ]
[ (boxer-quot) >>boxer-quot ] tri drop [ (unboxer-quot) >>unboxer-quot ]
[ (boxer-quot) >>boxer-quot ]
[ >>boxed-class ]
} cleave drop
] bi ; ] bi ;
: align-offset ( offset class -- offset' ) : align-offset ( offset class -- offset' )
@ -121,15 +132,15 @@ M: struct-class writer-quot
: struct-offsets ( slots -- size ) : struct-offsets ( slots -- size )
0 [ 0 [
[ class>> align-offset ] keep [ c-type>> align-offset ] keep
[ (>>offset) ] [ class>> heap-size + ] 2bi [ (>>offset) ] [ c-type>> heap-size + ] 2bi
] reduce ; ] reduce ;
: union-struct-offsets ( slots -- size ) : union-struct-offsets ( slots -- size )
[ 0 >>offset class>> heap-size ] [ max ] map-reduce ; [ 0 >>offset c-type>> heap-size ] [ max ] map-reduce ;
: struct-align ( slots -- align ) : struct-align ( slots -- align )
[ class>> c-type-align ] [ max ] map-reduce ; [ c-type>> c-type-align ] [ max ] map-reduce ;
M: struct-class c-type M: struct-class c-type
name>> c-type ; name>> c-type ;
@ -153,9 +164,6 @@ M: struct-class c-type-unboxer-quot
M: struct-class heap-size M: struct-class heap-size
"struct-size" word-prop ; "struct-size" word-prop ;
M: struct-class direct-array-of
<direct-struct-array> ;
! class definition ! class definition
: struct-prototype ( class -- prototype ) : struct-prototype ( class -- prototype )
@ -168,6 +176,10 @@ M: struct-class direct-array-of
over [ swapd [ call( value struct -- ) ] curry keep ] [ 2drop ] if over [ swapd [ call( value struct -- ) ] curry keep ] [ 2drop ] if
] each ; ] each ;
: (struct-methods) ( class -- )
[ (define-struct-slot-values-method) ]
[ (define-byte-length-method) ] bi ;
: (struct-word-props) ( class slots size align -- ) : (struct-word-props) ( class slots size align -- )
[ [
[ "struct-slots" set-word-prop ] [ "struct-slots" set-word-prop ]
@ -177,10 +189,10 @@ M: struct-class direct-array-of
[ "struct-align" set-word-prop ] tri-curry* [ "struct-align" set-word-prop ] tri-curry*
[ tri ] 3curry [ tri ] 3curry
[ dup struct-prototype "prototype" set-word-prop ] [ dup struct-prototype "prototype" set-word-prop ]
[ (define-struct-slot-values-method) ] tri ; [ (struct-methods) ] tri ;
: check-struct-slots ( slots -- ) : check-struct-slots ( slots -- )
[ class>> c-type drop ] each ; [ c-type>> c-type drop ] each ;
: (define-struct-class) ( class slots offsets-quot -- ) : (define-struct-class) ( class slots offsets-quot -- )
[ drop struct f define-tuple-class ] [ drop struct f define-tuple-class ]
@ -197,8 +209,27 @@ M: struct-class direct-array-of
: define-union-struct-class ( class slots -- ) : define-union-struct-class ( class slots -- )
[ union-struct-offsets ] (define-struct-class) ; [ union-struct-offsets ] (define-struct-class) ;
ERROR: invalid-struct-slot token ;
: struct-slot-class ( c-type -- class' )
c-type c-type-boxed-class
dup \ byte-array = [ drop \ c-ptr ] when ;
: parse-struct-slot ( -- slot )
struct-slot-spec new
scan >>name
scan [ >>c-type ] [ struct-slot-class >>class ] bi
\ } parse-until [ dup empty? ] [ peel-off-attributes ] until drop ;
: parse-struct-slots ( slots -- slots' more? )
scan {
{ ";" [ f ] }
{ "{" [ parse-struct-slot over push t ] }
[ invalid-struct-slot ]
} case ;
: parse-struct-definition ( -- class slots ) : parse-struct-definition ( -- class slots )
CREATE-CLASS [ parse-tuple-slots ] { } make ; CREATE-CLASS 8 <vector> [ parse-struct-slots ] [ ] while >array ;
SYNTAX: STRUCT: SYNTAX: STRUCT:
parse-struct-definition define-struct-class ; parse-struct-definition define-struct-class ;